diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-08-18 20:04:07 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-08-18 20:04:07 +0000 |
commit | 2e420b8b99db4a5b81e2deda1ca386d59ad6bcba (patch) | |
tree | e19ca16f7f829d6b72e822ebd8cf5804ef7451e4 | |
parent | 17d20383ef2072745fdc305c4c9105b63a4b0c76 (diff) |
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
-rw-r--r-- | thread.c | 11 | ||||
-rw-r--r-- | thread_sync.c | 5 |
2 files changed, 11 insertions, 5 deletions
@@ -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); diff --git a/thread_sync.c b/thread_sync.c index 5e511af0db..7b1054b2ac 100644 --- a/thread_sync.c +++ b/thread_sync.c @@ -438,7 +438,7 @@ rb_mutex_cleanup_keeping_mutexes(const rb_thread_t *current_thread) static VALUE rb_mutex_sleep_forever(VALUE time) { - rb_thread_sleep_deadly_allow_spurious_wakeup(); + sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE|SLEEP_BEFORE_CHECK_INTS); return Qnil; } @@ -446,7 +446,8 @@ static VALUE rb_mutex_wait_for(VALUE time) { struct timespec *t = (struct timespec*)time; - sleep_timespec(GET_THREAD(), *t, 0); /* permit spurious check */ + /* permit spurious check */ + sleep_timespec(GET_THREAD(), *t, SLEEP_BEFORE_CHECK_INTS); return Qnil; } |