From ed632cd0bacc710b03809c903a978d3fa2cfedfe Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 15 May 2025 13:00:18 +0200 Subject: [PATCH] Add missing lock in `rb_gc_impl_undefine_finalizer` The table is global so accesses must be synchronized. --- gc/default/default.c | 4 ++++ gc/mmtk/mmtk.c | 4 ++++ test/objspace/test_ractor.rb | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/gc/default/default.c b/gc/default/default.c index da1438c2fe..6d5e7a35a3 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -2774,7 +2774,11 @@ rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj) GC_ASSERT(!OBJ_FROZEN(obj)); st_data_t data = obj; + + int lev = rb_gc_vm_lock(); st_delete(finalizer_table, &data, 0); + rb_gc_vm_unlock(lev); + FL_UNSET(obj, FL_FINALIZE); } diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 59bef826bf..aec48df07a 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -966,7 +966,11 @@ rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj) struct objspace *objspace = objspace_ptr; st_data_t data = obj; + + int lev = rb_gc_vm_lock(); st_delete(objspace->finalizer_table, &data, 0); + rb_gc_vm_unlock(lev); + FL_UNSET(obj, FL_FINALIZE); } diff --git a/test/objspace/test_ractor.rb b/test/objspace/test_ractor.rb index 4901eeae2e..c5bb656da6 100644 --- a/test/objspace/test_ractor.rb +++ b/test/objspace/test_ractor.rb @@ -14,4 +14,23 @@ class TestObjSpaceRactor < Test::Unit::TestCase end RUBY end + + def test_undefine_finalizer + assert_ractor(<<~'RUBY', require: 'objspace') + def fin + ->(id) { } + end + ractors = 5.times.map do + Ractor.new do + 10_000.times do + o = Object.new + ObjectSpace.define_finalizer(o, fin) + ObjectSpace.undefine_finalizer(o) + end + end + end + + ractors.each(&:take) + RUBY + end end