summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@shopify.com>2025-06-06 09:38:57 +0900
committerGitHub <noreply@github.com>2025-06-06 09:38:57 +0900
commitf0cf4dce65ba7bf3dc6787e10b88e08b411e2c92 (patch)
treeb5a85f799d58985d1b3f5d088a2cdf77eed00a03 /thread.c
parente66ac2a743a03bd1af99c3d56b0ec94edfd423e8 (diff)
Handle spurious wakeups in `Thread#join`. (#13532)
Notes
Notes: Merged-By: ioquatix <samuel@codeotaku.com>
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/thread.c b/thread.c
index 4ab36c6cff..3530173c79 100644
--- a/thread.c
+++ b/thread.c
@@ -1052,23 +1052,28 @@ thread_join_sleep(VALUE arg)
while (!thread_finished(target_th)) {
VALUE scheduler = rb_fiber_scheduler_current();
- if (scheduler != Qnil) {
- rb_fiber_scheduler_block(scheduler, target_th->self, p->timeout);
- // Check if the target thread is finished after blocking:
- if (thread_finished(target_th)) break;
- // Otherwise, a timeout occurred:
- else return Qfalse;
- }
- else if (!limit) {
- sleep_forever(th, SLEEP_DEADLOCKABLE | SLEEP_ALLOW_SPURIOUS | SLEEP_NO_CHECKINTS);
+ if (!limit) {
+ if (scheduler != Qnil) {
+ rb_fiber_scheduler_block(scheduler, target_th->self, Qnil);
+ }
+ else {
+ sleep_forever(th, SLEEP_DEADLOCKABLE | SLEEP_ALLOW_SPURIOUS | SLEEP_NO_CHECKINTS);
+ }
}
else {
if (hrtime_update_expire(limit, end)) {
RUBY_DEBUG_LOG("timeout target_th:%u", rb_th_serial(target_th));
return Qfalse;
}
- th->status = THREAD_STOPPED;
- native_sleep(th, limit);
+
+ if (scheduler != Qnil) {
+ VALUE timeout = rb_float_new(hrtime2double(*limit));
+ rb_fiber_scheduler_block(scheduler, target_th->self, timeout);
+ }
+ else {
+ th->status = THREAD_STOPPED;
+ native_sleep(th, limit);
+ }
}
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
th->status = THREAD_RUNNABLE;
@@ -1749,6 +1754,7 @@ io_blocking_operation_exit(VALUE _arguments)
rb_fiber_t *fiber = io->closing_ec->fiber_ptr;
if (thread->scheduler != Qnil) {
+ // This can cause spurious wakeups...
rb_fiber_scheduler_unblock(thread->scheduler, io->self, rb_fiberptr_self(fiber));
}
else {