From 5ca416bdf6b6785cb20f139c2c514eda005fe42f Mon Sep 17 00:00:00 2001 From: normal Date: Mon, 6 Aug 2018 01:06:21 +0000 Subject: [PATCH] process.c: ensure th->interrupt lock is held when migrating w->cond may be changed without our knowledge in waitpid_nogvl without th->interrupt_lock git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64201 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- process.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/process.c b/process.c index 11ecc59b0f..43db055cbf 100644 --- a/process.c +++ b/process.c @@ -941,6 +941,24 @@ int rb_sigwait_fd_get(const rb_thread_t *); void rb_sigwait_sleep(const rb_thread_t *, int fd, const struct timespec *); void rb_sigwait_fd_put(const rb_thread_t *, int fd); +static int +sigwait_fd_migrate_signaled_p(struct waitpid_state *w) +{ + int signaled = FALSE; + rb_thread_t *th = w->ec ? rb_ec_thread_ptr(w->ec) : 0; + + if (th) rb_native_mutex_lock(&th->interrupt_lock); + + if (w->cond) { + rb_native_cond_signal(w->cond); + signaled = TRUE; + } + + if (th) rb_native_mutex_unlock(&th->interrupt_lock); + + return signaled; +} + /* * When a thread is done using sigwait_fd and there are other threads * sleeping on waitpid, we must kick one of the threads out of @@ -952,14 +970,10 @@ sigwait_fd_migrate_sleeper(rb_vm_t *vm) struct waitpid_state *w = 0; list_for_each(&vm->waiting_pids, w, wnode) { - if (!w->cond) continue; /* somebody else already got sigwait_fd */ - rb_native_cond_signal(w->cond); - return; + if (sigwait_fd_migrate_signaled_p(w)) return; } list_for_each(&vm->waiting_grps, w, wnode) { - if (!w->cond) continue; /* somebody else already got sigwait_fd */ - rb_native_cond_signal(w->cond); - return; + if (sigwait_fd_migrate_signaled_p(w)) return; } }