mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Do not count a not-yet-running thread as a Ractor barrier waiter
`rb_ractor_sched_barrier_join` unconditionally did `barrier_waiting_cnt++`. A thread can reach it (via `vm_lock_enter`) while its Ractor's `sched.running` is set but the thread is not yet in the VM running set (`sched.is_running == false`) -- e.g. resuming from a blocking IO wait. Counting such a thread pushes `barrier_waiting_cnt` past `running_cnt - 1` and trips `VM_ASSERT(running_cnt - 1 >= barrier_waiting_cnt)` in `ractor_sched_barrier_completed_p`; in release builds the unsigned `(running_cnt - barrier_waiting_cnt) == 1` completion test can underflow. Increment `barrier_waiting_cnt` only when `cr->threads.sched.is_running` (O(1), toggled together with running_threads add/del). A not-running thread is parked at the barrier regardless, so it is safe to wait without counting. NOTE (open): this guards the count at the join site. A stricter fix would prevent a not-running thread from reaching barrier_join at all; that needs care so it still waits for the barrier rather than proceeding during compaction. Left for review. Reproduction is currently coupled with a separate pre-existing compaction use-after-poison on a blocked-IO thread's STR_TMPLOCK buffer (only the IO-read blocking path triggers this barrier window), so a standalone passing test awaits that fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f3e4fc4fee
commit
3fa1c87089
1 file changed
+10
-4
Notes:
git
2026-07-11 03:04:22 +00:00
+10
-4
@@ -1664,10 +1664,16 @@ rb_ractor_sched_barrier_join(rb_vm_t *vm, rb_ractor_t *cr)
|
||||
ractor_sched_lock(vm, cr);
|
||||
{
|
||||
// running_cnt
|
||||
vm->ractor.sched.barrier_waiting_cnt++;
|
||||
RUBY_DEBUG_LOG("waiting_cnt:%u serial:%u", vm->ractor.sched.barrier_waiting_cnt, barrier_serial);
|
||||
|
||||
ractor_sched_barrier_join_signal_locked(vm);
|
||||
/* A not-yet-running thread (blocking/terminating, joined only to
|
||||
* sync) must not be counted, or barrier_waiting_cnt > running_cnt-1. */
|
||||
if (cr->threads.sched.is_running) {
|
||||
vm->ractor.sched.barrier_waiting_cnt++;
|
||||
RUBY_DEBUG_LOG("waiting_cnt:%u serial:%u", vm->ractor.sched.barrier_waiting_cnt, barrier_serial);
|
||||
ractor_sched_barrier_join_signal_locked(vm);
|
||||
}
|
||||
else {
|
||||
RUBY_DEBUG_LOG("join without counting (not running) serial:%u", barrier_serial);
|
||||
}
|
||||
ractor_sched_barrier_join_wait_locked(vm, cr->threads.sched.running);
|
||||
}
|
||||
ractor_sched_unlock(vm, cr);
|
||||
|
||||
Reference in new issue
Block a user