aboutsummaryrefslogtreecommitdiffstats
path: root/thread.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-18 20:04:07 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-18 20:04:07 +0000
commitd428911901fd843952c9564e4cc4aee448461bd3 (patch)
treee19ca16f7f829d6b72e822ebd8cf5804ef7451e4 /thread.c
parentcf87de3d550419caa54aa00b22441b8d450faf05 (diff)
downloadruby-d428911901fd843952c9564e4cc4aee448461bd3.tar.gz
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
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c11
1 files changed, 8 insertions, 3 deletions
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);