1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
normal 2018-08-18 20:04:07 +00:00
parent 17d20383ef
commit 2e420b8b99
2 changed files with 11 additions and 5 deletions

View file

@ -94,7 +94,8 @@ static ID id_locals;
enum SLEEP_FLAGS { enum SLEEP_FLAGS {
SLEEP_DEADLOCKABLE = 0x1, 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); 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; status = fl & SLEEP_DEADLOCKABLE ? THREAD_STOPPED_FOREVER : THREAD_STOPPED;
th->status = status; 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) { while (th->status == status) {
if (fl & SLEEP_DEADLOCKABLE) { if (fl & SLEEP_DEADLOCKABLE) {
th->vm->sleeper++; th->vm->sleeper++;
@ -1293,7 +1296,9 @@ sleep_timespec(rb_thread_t *th, struct timespec ts, unsigned int fl)
getclockofday(&end); getclockofday(&end);
timespec_add(&end, &ts); timespec_add(&end, &ts);
th->status = THREAD_STOPPED; 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) { while (th->status == THREAD_STOPPED) {
native_sleep(th, &ts); native_sleep(th, &ts);
woke = vm_check_ints_blocking(th->ec); woke = vm_check_ints_blocking(th->ec);

View file

@ -438,7 +438,7 @@ rb_mutex_cleanup_keeping_mutexes(const rb_thread_t *current_thread)
static VALUE static VALUE
rb_mutex_sleep_forever(VALUE time) 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; return Qnil;
} }
@ -446,7 +446,8 @@ static VALUE
rb_mutex_wait_for(VALUE time) rb_mutex_wait_for(VALUE time)
{ {
struct timespec *t = (struct timespec*)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; return Qnil;
} }