Skip to content

Commit 6ae5083

Browse files
committed
gc: prevent LTO from eliminating rb_gc_before_fork
GCC LTO with -flto=auto creates a constprop clone of rb_fork_ruby where rb_multi_ractor_p() is constant false. In that clone, rb_gc_vm_barrier() and RB_GC_VM_LOCK() are both no-ops, so rb_gc_impl_before_fork reduces to a trivial store and GCC eliminates the entire call chain. This leaves no GC barrier before fork(2). RBIMPL_ATTR_NOINLINE() on rb_gc_before_fork prevents GCC from inlining it into the constprop clone, forcing it to treat the call as having unknown side effects. Additionally, call gc_rest() at the top of rb_gc_impl_before_fork to complete any in-progress incremental GC cycle before forking. This ensures the child does not inherit a mid-cycle heap.
1 parent 8913322 commit 6ae5083

File tree

2 files changed

+3
-0
lines changed

2 files changed

+3
-0
lines changed

gc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5435,6 +5435,7 @@ rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func)
54355435
fprintf(stderr, "<OBJ_INFO:%s@%s:%d> %s\n", func, file, line, rb_raw_obj_info(buff, 0x100, obj));
54365436
}
54375437

5438+
RBIMPL_ATTR_NOINLINE()
54385439
void
54395440
rb_gc_before_fork(void)
54405441
{

gc/default/default.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9407,6 +9407,8 @@ rb_gc_impl_before_fork(void *objspace_ptr)
94079407
{
94089408
rb_objspace_t *objspace = objspace_ptr;
94099409

9410+
gc_rest(objspace);
9411+
94109412
objspace->fork_vm_lock_lev = RB_GC_VM_LOCK();
94119413
rb_gc_vm_barrier();
94129414
}

0 commit comments

Comments
 (0)