aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gc.c15
-rw-r--r--test/ruby/test_gc.rb22
2 files changed, 29 insertions, 8 deletions
diff --git a/gc.c b/gc.c
index ad83006ea0..8525085541 100644
--- a/gc.c
+++ b/gc.c
@@ -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