diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 00ac1487c6..94c0635c72 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -2210,3 +2210,10 @@ assert_equal 'ok', %q{ end 'ok' } + +# fork after creating Ractor +assert_equal 'ok', %q{ + Ractor.new { Ractor.receive } + _, status = Process.waitpid2 fork { } + status.success? ? "ok" : status +} diff --git a/ractor.c b/ractor.c index 1b66f2dda5..c536d27e4e 100644 --- a/ractor.c +++ b/ractor.c @@ -2072,6 +2072,8 @@ rb_ractor_main_alloc(void) } #if defined(HAVE_WORKING_FORK) +// Set up the main Ractor for the VM after fork. +// Puts us in "single Ractor mode" void rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th) { @@ -2087,6 +2089,14 @@ rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th) VM_ASSERT(vm->ractor.blocking_cnt == 0); VM_ASSERT(vm->ractor.cnt == 1); } + +void +rb_ractor_terminate_atfork(rb_vm_t *vm, rb_ractor_t *r) +{ + rb_gc_ractor_cache_free(r->newobj_cache); + r->newobj_cache = NULL; + r->status_ = ractor_terminated; +} #endif void rb_thread_sched_init(struct rb_thread_sched *, bool atfork); diff --git a/ractor_core.h b/ractor_core.h index 1e860edb4b..51fb3246ac 100644 --- a/ractor_core.h +++ b/ractor_core.h @@ -223,6 +223,7 @@ void rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r); void rb_ractor_terminate_all(void); bool rb_ractor_main_p_(void); void rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th); +void rb_ractor_terminate_atfork(rb_vm_t *vm, rb_ractor_t *th); VALUE rb_ractor_require(VALUE feature); VALUE rb_ractor_autoload_load(VALUE space, ID id); diff --git a/thread.c b/thread.c index d09767cb75..e56545e1c0 100644 --- a/thread.c +++ b/thread.c @@ -4740,6 +4740,9 @@ rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const r // OK. Only this thread accesses: ccan_list_for_each(&vm->ractor.set, r, vmlr_node) { + if (r != vm->ractor.main_ractor) { + rb_ractor_terminate_atfork(vm, r); + } ccan_list_for_each(&r->threads.set, i, lt_node) { atfork(i, th); }