Skip to content

Commit 0c183c9

Browse files
Fix GC safety in rb_fiber_scheduler_blocking_operation_wait
Extract the raw operation pointer before rb_funcall so it is obtained while the GVL is held and no fiber switch has occurred yet. Place RB_GC_GUARD(blocking_operation) after the last implicit use of the VALUE — all accesses via the derived `operation` pointer — so the compiler cannot treat blocking_operation as dead before this point, keeping it reachable as a GC root through rb_funcall and through all subsequent uses of the raw pointer. See: socketry/io-event#172 Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 56cd26f commit 0c183c9

1 file changed

Lines changed: 3 additions & 0 deletions

File tree

scheduler.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,7 @@ VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*functi
11021102

11031103
// Get the operation data to check if it was executed
11041104
rb_fiber_scheduler_blocking_operation_t *operation = get_blocking_operation(blocking_operation);
1105+
11051106
rb_atomic_t current_status = RUBY_ATOMIC_LOAD(operation->status);
11061107

11071108
// Invalidate the operation now that we're done with it
@@ -1111,6 +1112,8 @@ VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*functi
11111112
operation->data2 = NULL;
11121113
operation->unblock_function = NULL;
11131114

1115+
RB_GC_GUARD(blocking_operation);
1116+
11141117
// If the blocking operation was never executed, return Qundef to signal the caller to use rb_nogvl instead
11151118
if (current_status == RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED) {
11161119
return Qundef;

0 commit comments

Comments
 (0)