Bug #15310 ยป 0001-thread_pthread.c-close-race-from-UBF_TIMER-and-non-G.patch
| configure.ac | ||
|---|---|---|
|
AC_CHECK_FUNCS(sigaction)
|
||
|
AC_CHECK_FUNCS(sigaltstack)
|
||
|
AC_CHECK_FUNCS(sigprocmask)
|
||
|
AC_CHECK_FUNCS(sigqueue)
|
||
|
AC_CHECK_FUNCS(sinh)
|
||
|
AC_CHECK_FUNCS(spawnv)
|
||
|
AC_CHECK_FUNCS(symlink)
|
||
| thread.c | ||
|---|---|---|
|
}
|
||
|
}
|
||
|
/* async-signal-safe */
|
||
|
static void
|
||
|
timer_thread_function(void)
|
||
|
{
|
||
|
volatile rb_execution_context_t *ec;
|
||
|
/* for time slice */
|
||
|
/* for time slice, this relies on GC for grace period */
|
||
|
ec = ACCESS_ONCE(rb_execution_context_t *,
|
||
|
ruby_current_execution_context_ptr);
|
||
|
if (ec) RUBY_VM_SET_TIMER_INTERRUPT(ec);
|
||
| thread_pthread.c | ||
|---|---|---|
|
#if defined(SIGVTALRM) && !defined(__CYGWIN__)
|
||
|
# define USE_UBF_LIST 1
|
||
|
static LIST_HEAD(ubf_list_head);
|
||
|
static rb_nativethread_lock_t ubf_list_lock = RB_NATIVETHREAD_LOCK_INIT;
|
||
|
#endif
|
||
|
/*
|
||
| ... | ... | |
|
static pthread_key_t ruby_native_thread_key;
|
||
|
#if defined(HAVE_SIGACTION) && defined(USE_UBF_LIST)
|
||
|
static void
|
||
|
null_func(int i)
|
||
|
vtalrm_func(int sig, siginfo_t *info, void *ctx)
|
||
|
{
|
||
|
/* null */
|
||
|
/*
|
||
|
* if triggered by UBF_TIMER, force running thread to call
|
||
|
* ubf_wakeup_all_threads via gvl_yield
|
||
|
*/
|
||
|
if (info && info->si_ptr == &ubf_list_head)
|
||
|
timer_thread_function();
|
||
|
}
|
||
|
#else /* do any platforms have pthreads, SIGVTALRM, but no sigaction? */
|
||
|
static void vtalrm_func(int sig) { /* noop */ }
|
||
|
#endif /* HAVE_SIGACTION && USE_UBF_LIST */
|
||
|
static rb_thread_t *
|
||
|
ruby_thread_from_native(void)
|
||
| ... | ... | |
|
th->thread_id = pthread_self();
|
||
|
fill_thread_id_str(th);
|
||
|
native_thread_init(th);
|
||
|
posix_signal(SIGVTALRM, null_func);
|
||
|
#if defined(HAVE_SIGACTION) && defined(USE_UBF_LIST)
|
||
|
{
|
||
|
struct sigaction sa;
|
||
|
sigemptyset(&sa.sa_mask);
|
||
|
sa.sa_sigaction = vtalrm_func;
|
||
|
sa.sa_flags = SA_SIGINFO;
|
||
|
if (sigaction(SIGVTALRM, &sa, 0) != 0)
|
||
|
rb_async_bug_errno("sigaction", errno);
|
||
|
}
|
||
|
#else
|
||
|
posix_signal(SIGVTALRM, vtalrm_func);
|
||
|
#endif
|
||
|
}
|
||
|
static void
|
||
| ... | ... | |
|
}
|
||
|
#ifdef USE_UBF_LIST
|
||
|
static LIST_HEAD(ubf_list_head);
|
||
|
static rb_nativethread_lock_t ubf_list_lock = RB_NATIVETHREAD_LOCK_INIT;
|
||
|
static void
|
||
|
ubf_list_atfork(void)
|
||
| ... | ... | |
|
if (setup_communication_pipe_internal(timer_pthread.low) < 0)
|
||
|
return;
|
||
|
err = pthread_create(&timer_pthread.thid, 0, timer_pthread_fn, GET_VM());
|
||
|
err = pthread_create(&timer_pthread.thid, 0, timer_pthread_fn, 0);
|
||
|
if (!err)
|
||
|
timer_pthread.owner = current;
|
||
|
else
|
||
| ... | ... | |
|
sev.sigev_notify = SIGEV_SIGNAL;
|
||
|
sev.sigev_signo = SIGVTALRM;
|
||
|
sev.sigev_value.sival_ptr = &timer_posix;
|
||
|
sev.sigev_value.sival_ptr = &ubf_list_head;
|
||
|
if (!timer_create(UBF_TIMER_CLOCK, &sev, &timer_posix.timerid))
|
||
|
timer_posix.owner = current;
|
||
|
else
|
||
| ... | ... | |
|
}
|
||
|
#if UBF_TIMER == UBF_TIMER_PTHREAD
|
||
|
static void
|
||
|
timer_pthread_sigqueue(rb_pid_t pid, int sig)
|
||
|
{
|
||
|
#if defined(HAVE_SIGQUEUE) && defined(HAVE_SIGACTION)
|
||
|
union sigval sv;
|
||
|
sv.sival_ptr = &ubf_list_head;
|
||
|
if (sigqueue(pid, sig, sv) != 0)
|
||
|
rb_async_bug_errno("sigqueue", errno);
|
||
|
#else
|
||
|
kill(pid, sig);
|
||
|
#endif
|
||
|
}
|
||
|
static void *
|
||
|
timer_pthread_fn(void *p)
|
||
|
timer_pthread_fn(void *ignore)
|
||
|
{
|
||
|
rb_vm_t *vm = p;
|
||
|
pthread_t main_thread_id = vm->main_thread->thread_id;
|
||
|
rb_pid_t pid = getpid();
|
||
|
struct pollfd pfd;
|
||
|
int timeout = -1;
|
||
| ... | ... | |
|
(void)consume_communication_pipe(pfd.fd);
|
||
|
if (system_working > 0 && ATOMIC_CAS(timer_pthread.armed, 1, 1)) {
|
||
|
pthread_kill(main_thread_id, SIGVTALRM);
|
||
|
timer_pthread_sigqueue(pid, SIGVTALRM);
|
||
|
if (rb_signal_buff_size() || !ubf_threads_empty()) {
|
||
|
timeout = TIME_QUANTUM_MSEC;
|
||
|
-
|
||