From 954094a910c2dcf459caeb61e20143df0864f914 Mon Sep 17 00:00:00 2001 From: Luke Gruber Date: Fri, 6 Feb 2026 16:08:57 -0500 Subject: Take VM Lock during rb_gc_{un}register_address (#16097) The `Rice` C++ library uses an Anchor class that uses RAII to call `rb_gc_register_address`, `rb_gc_unregister_address` during init+destruct. It's unclear if this API is meant to be used at runtime like this, but we can at least lock the VM so it works safely across Ractors and doesn't mangle the `global_object_list` table. --- gc.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/gc.c b/gc.c index 53a65d6acb..4e1bb39e21 100644 --- a/gc.c +++ b/gc.c @@ -3633,9 +3633,11 @@ rb_gc_register_address(VALUE *addr) VALUE obj = *addr; struct global_object_list *tmp = ALLOC(struct global_object_list); - tmp->next = vm->global_object_list; - tmp->varptr = addr; - vm->global_object_list = tmp; + RB_VM_LOCKING() { + tmp->next = vm->global_object_list; + tmp->varptr = addr; + vm->global_object_list = tmp; + } /* * Because some C extensions have assignment-then-register bugs, @@ -3653,22 +3655,25 @@ void rb_gc_unregister_address(VALUE *addr) { rb_vm_t *vm = GET_VM(); - struct global_object_list *tmp = vm->global_object_list; - - if (tmp->varptr == addr) { - vm->global_object_list = tmp->next; - SIZED_FREE(tmp); - return; - } - while (tmp->next) { - if (tmp->next->varptr == addr) { - struct global_object_list *t = tmp->next; + struct global_object_list *tmp; + RB_VM_LOCKING() { + tmp = vm->global_object_list; + if (tmp->varptr == addr) { + vm->global_object_list = tmp->next; + SIZED_FREE(tmp); + } + else { + while (tmp->next) { + if (tmp->next->varptr == addr) { + struct global_object_list *t = tmp->next; - tmp->next = tmp->next->next; - SIZED_FREE(t); - break; + tmp->next = tmp->next->next; + SIZED_FREE(t); + break; + } + tmp = tmp->next; + } } - tmp = tmp->next; } } -- cgit v1.2.3