diff options
| author | Samuel Williams <samuel.williams@shopify.com> | 2025-06-06 09:38:57 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-06 09:38:57 +0900 |
| commit | f0cf4dce65ba7bf3dc6787e10b88e08b411e2c92 (patch) | |
| tree | b5a85f799d58985d1b3f5d088a2cdf77eed00a03 /thread.c | |
| parent | e66ac2a743a03bd1af99c3d56b0ec94edfd423e8 (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.c | 28 |
1 files changed, 17 insertions, 11 deletions
@@ -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 { |
