Bug #9205
closedAssertion failed: heap_pages_deferred_final == 0
Description
If I run the following code:
raise_proc = proc do |id|
p "Finalizer one on #{id}"
end
10000.times do
ObjectSpace.define_finalizer(Object.new, raise_proc)
end
I can see an assertion failure.
"Finalizer one on 24535120"
Assertion failed: heap_pages_deferred_final == 0, file gc.c, line 2111
Same error with ruby 2.0.0p353 (2013-11-22) [i386-mingw32]
Files
Updated by phasis68 (Heesob Park) about 11 years ago
- File fix_assertion_fail.patch fix_assertion_fail.patch added
I found that make_deferred function of gc.c modified the value of heap_pages_deferred_final to nonzero.
I made a draft patch and I am not sure this patch is the best.
Anyway, it fixed the assertion and passed test-all.
Updated by nobu (Nobuyoshi Nakada) about 11 years ago
It doesn't seem nice to just ignore finalizers while running other finalizers.
diff --git c/gc.c i/gc.c
index ddf607c..0d18031 100644
--- c/gc.c
+++ i/gc.c
@@ -2055,10 +2055,10 @@ finalize_list(rb_objspace_t *objspace, RVALUE *p)
static void
finalize_deferred(rb_objspace_t *objspace)
{
- RVALUE *p = heap_pages_deferred_final;
- heap_pages_deferred_final = 0;
+ RVALUE *p;
- if (p) {
+ while ((p = heap_pages_deferred_final) != 0) {
+ heap_pages_deferred_final = 0;
finalize_list(objspace, p);
}
}
diff --git c/test/ruby/test_gc.rb i/test/ruby/test_gc.rb
index 034a330..2b1e6a5 100644
--- c/test/ruby/test_gc.rb
+++ i/test/ruby/test_gc.rb
@@ -238,4 +238,19 @@ class TestGc < Test::Unit::TestCase
assert_not_nil GC::INTERNAL_CONSTANTS[:HEAP_OBJ_LIMIT]
assert_not_nil GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
end
+
+ def test_raise_in_finalizer
+ bug9205 = '[ruby-core:58833] [Bug #9205]'
+ 100.times do
+ assert_ruby_status([], <<-'end;', bug9205)
+ STDOUT.sync = true
+ raise_proc = proc do |id|
+ p "Finalizer one on #{id}"
+ end
+ 10000.times do
+ ObjectSpace.define_finalizer(Object.new, raise_proc)
+ end
+ end;
+ end
+ end
end
Updated by phasis68 (Heesob Park) about 11 years ago
You are right.
Why not commit your patch?
Updated by nobu (Nobuyoshi Nakada) about 11 years ago
I've misread the code, like as raise_proc
raises an exception and that triggers the failure.
But the proc raises nothing, then what would trigger it?
Updated by phasis68 (Heesob Park) about 11 years ago
My test code is different from Bug #9168.
I guess the name raise_proc
made confusion.
It is just repeated finalizer test without raising an exception.
Updated by nobu (Nobuyoshi Nakada) about 11 years ago
- Status changed from Open to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r43994.
Heesob, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.
gc.c: flush all deferred finalizers
- gc.c (
finalize_deferred
): flush all deferred finalizers while other
finalizers can get ready to run newly by lazy sweep.
[ruby-core:58833] [Bug #9205]
Updated by nagachika (Tomoyuki Chikanaga) about 11 years ago
- Backport changed from 1.9.3: UNKNOWN, 2.0.0: UNKNOWN to 1.9.3: UNKNOWN, 2.0.0: REQUIRED
Updated by nagachika (Tomoyuki Chikanaga) about 11 years ago
- Backport changed from 1.9.3: UNKNOWN, 2.0.0: REQUIRED to 1.9.3: UNKNOWN, 2.0.0: DONE
r43994 was backported to ruby_2_0_0
at r44319.
Updated by nagachika (Tomoyuki Chikanaga) about 11 years ago
... and r44000 was also backported to ruby_2_0_0
at r44322.
Updated by usa (Usaku NAKAMURA) almost 11 years ago
- Related to Backport #9463: SEGV when calling GC.start in a finalizer added
Updated by usa (Usaku NAKAMURA) almost 11 years ago
- Backport changed from 1.9.3: UNKNOWN, 2.0.0: DONE to 1.9.3: DONE, 2.0.0: DONE
backported into ruby_1_9_3
at r44764.