Skip to content

Commit 79d3357

Browse files
Fix GC safety of blocking_operation in rb_fiber_scheduler_blocking_operation_wait
rb_funcall(scheduler, :blocking_operation_wait, 1, blocking_operation) can cause a fiber switch if the scheduler calls rb_fiber_scheduler_block. When the fiber is suspended, blocking_operation may not be reachable via the conservative GC scan of the suspended fiber's C stack. rb_gc_register_address pins blocking_operation in the global GC root list, which is always walked regardless of fiber state. The address is kept registered through the last implicit use of the VALUE — including all accesses via the raw C pointer derived from it — so that a compacting GC cannot move the object and leave dangling. Confirmed by reproducing the crash in io-event CI: ./configure --enable-shared --disable-install-doc --enable-yjit See: socketry/io-event#171 ruby#16908 Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 56cd26f commit 79d3357

1 file changed

Lines changed: 7 additions & 0 deletions

File tree

scheduler.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,13 @@ VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*functi
11111111
operation->data2 = NULL;
11121112
operation->unblock_function = NULL;
11131113

1114+
// RB_GC_GUARD must come after the last implicit use of blocking_operation,
1115+
// which includes all accesses via the raw `operation` pointer derived from it.
1116+
// Placing it here ensures the compiler cannot treat blocking_operation as dead
1117+
// before this point — keeping it reachable as a GC root through rb_funcall and
1118+
// through all subsequent uses of the extracted operation pointer.
1119+
RB_GC_GUARD(blocking_operation);
1120+
11141121
// If the blocking operation was never executed, return Qundef to signal the caller to use rb_nogvl instead
11151122
if (current_status == RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED) {
11161123
return Qundef;

0 commit comments

Comments
 (0)