From 2e420b8b99db4a5b81e2deda1ca386d59ad6bcba Mon Sep 17 00:00:00 2001 From: normal Date: Sat, 18 Aug 2018 20:04:07 +0000 Subject: thread_sync.c (rb_mutex_sleep): skip interrupt check before sleep We do not want to risk switching threads before going to sleep because it can cause unexpected wakeups and put us in an unexpected state when used with ConditionVariable. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64464 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- thread.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index 8254c7dc0c..4a34081509 100644 --- a/thread.c +++ b/thread.c @@ -94,7 +94,8 @@ static ID id_locals; enum SLEEP_FLAGS { SLEEP_DEADLOCKABLE = 0x1, - SLEEP_SPURIOUS_CHECK = 0x2 + SLEEP_SPURIOUS_CHECK = 0x2, + SLEEP_BEFORE_CHECK_INTS = 0x4 }; static void sleep_timespec(rb_thread_t *, struct timespec, unsigned int fl); @@ -1187,7 +1188,9 @@ sleep_forever(rb_thread_t *th, unsigned int fl) status = fl & SLEEP_DEADLOCKABLE ? THREAD_STOPPED_FOREVER : THREAD_STOPPED; th->status = status; - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + if (!(fl & SLEEP_BEFORE_CHECK_INTS)) { + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + } while (th->status == status) { if (fl & SLEEP_DEADLOCKABLE) { th->vm->sleeper++; @@ -1293,7 +1296,9 @@ sleep_timespec(rb_thread_t *th, struct timespec ts, unsigned int fl) getclockofday(&end); timespec_add(&end, &ts); th->status = THREAD_STOPPED; - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + if (!(fl & SLEEP_BEFORE_CHECK_INTS)) { + RUBY_VM_CHECK_INTS_BLOCKING(th->ec); + } while (th->status == THREAD_STOPPED) { native_sleep(th, &ts); woke = vm_check_ints_blocking(th->ec); -- cgit v1.2.3