diff options
-rw-r--r-- | gc.c | 15 | ||||
-rw-r--r-- | test/ruby/test_gc.rb | 22 |
2 files changed, 29 insertions, 8 deletions
@@ -2796,16 +2796,15 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table) saved.finished = 0; TH_PUSH_TAG(th); - if ((state = TH_EXEC_TAG()) == TAG_NONE) { - for (i = saved.finished; - RESTORE_FINALIZER(), i<RARRAY_LEN(table); - saved.finished = ++i) { - run_single_final(RARRAY_AREF(table, i), saved.objid); - } - } - else { + state = TH_EXEC_TAG(); + if (state != TAG_NONE) { ++saved.finished; /* skip failed finalizer */ } + for (i = saved.finished; + RESTORE_FINALIZER(), i<RARRAY_LEN(table); + saved.finished = ++i) { + run_single_final(RARRAY_AREF(table, i), saved.objid); + } TH_POP_TAG(); #undef RESTORE_FINALIZER } diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index a5fd2897a2..2e26fde5c1 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -397,4 +397,26 @@ class TestGc < Test::Unit::TestCase ObjectSpace.each_object{|o| case o when Module then o.instance_methods end} end end + + def test_exception_in_finalizer + result = [] + c1 = proc do + result << :c1 + raise + end + c2 = proc do + result << :c2 + raise + end + tap { + tap { + obj = Object.new + ObjectSpace.define_finalizer(obj, c1) + ObjectSpace.define_finalizer(obj, c2) + obj = nil + } + } + GC.start + assert_equal([:c1, :c2], result) + end end |