Project

General

Profile

Bug #15310 ยป 0001-thread_pthread.c-close-race-from-UBF_TIMER-and-non-G.patch

normalperson (Eric Wong), 11/16/2018 02:30 AM

View differences:

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;
-
    (1-1/1)