diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-08-06 11:48:30 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-08-06 11:48:30 +0000 |
commit | faf2541c2be5e8438675a17002c8c9d4484f572c (patch) | |
tree | 656acdce1baee974f1feca9b89995e5a0ce98982 | |
parent | 5adb2479140a19ea446cd46f8059d9f0306ff562 (diff) | |
download | ruby-faf2541c2be5e8438675a17002c8c9d4484f572c.tar.gz |
* gc.c (rb_gc_call_finalizer_at_exit): self-referencing finalizers
cannot be invoked. [ruby-dev:35681]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18391 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | bootstraptest/test_finalizer.rb | 8 | ||||
-rw-r--r-- | gc.c | 35 |
3 files changed, 28 insertions, 20 deletions
@@ -1,3 +1,8 @@ +Wed Aug 6 20:48:27 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * gc.c (rb_gc_call_finalizer_at_exit): self-referencing finalizers + cannot be invoked. [ruby-dev:35681] + Wed Aug 6 20:44:41 2008 Tanaka Akira <akr@fsij.org> * tool/transcode-tblgen.rb: distinguish UNDEF and INVALID. diff --git a/bootstraptest/test_finalizer.rb b/bootstraptest/test_finalizer.rb new file mode 100644 index 0000000000..22a16b1220 --- /dev/null +++ b/bootstraptest/test_finalizer.rb @@ -0,0 +1,8 @@ +assert_normal_exit %q{ +a1,a2,b1,b2=Array.new(4){""} +ObjectSpace.define_finalizer(b2,proc{}) +ObjectSpace.define_finalizer(b1,proc{b1.inspect}) + +ObjectSpace.define_finalizer(a2,proc{a1.inspect}) +ObjectSpace.define_finalizer(a1,proc{}) +}, '[ruby-dev:35778]' @@ -1489,6 +1489,12 @@ rb_gc_force_recycle(VALUE p) add_freelist(objspace, (RVALUE *)p); } +static inline void +make_deferred(RVALUE *p) +{ + p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_DEFERRED; +} + static int obj_free(rb_objspace_t *objspace, VALUE obj) { @@ -1546,14 +1552,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj) xfree(DATA_PTR(obj)); } else if (RANY(obj)->as.data.dfree) { - if (1) { - RANY(obj)->as.basic.flags &= ~T_MASK; - RANY(obj)->as.basic.flags |= T_DEFERRED; - return 1; - } - else { - (*RANY(obj)->as.data.dfree)(DATA_PTR(obj)); - } + make_deferred(RANY(obj)); + return 1; } } break; @@ -1562,23 +1562,17 @@ obj_free(rb_objspace_t *objspace, VALUE obj) struct rmatch *rm = RANY(obj)->as.match.rmatch; onig_region_free(&rm->regs, 0); if (rm->char_offset) - xfree(rm->char_offset); + xfree(rm->char_offset); xfree(rm); } break; case T_FILE: if (RANY(obj)->as.file.fptr) { rb_io_t *fptr = RANY(obj)->as.file.fptr; - if (1) { - RANY(obj)->as.basic.flags &= ~T_MASK; - RANY(obj)->as.basic.flags |= T_DEFERRED; - RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize; - RDATA(obj)->data = fptr; - return 1; - } - else { - rb_io_fptr_finalize(fptr); - } + make_deferred(RANY(obj)); + RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize; + RDATA(obj)->data = fptr; + return 1; } break; case T_RATIONAL: @@ -2091,7 +2085,7 @@ static int chain_finalized_object(st_data_t key, st_data_t val, st_data_t arg) { RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg; - if (p->as.basic.flags & FL_FINALIZE) { + if ((p->as.basic.flags & (FL_FINALIZE|FL_MARK)) == FL_FINALIZE) { if (BUILTIN_TYPE(p) != T_DEFERRED) { p->as.free.flags = FL_MARK | T_DEFERRED; /* remain marked */ RDATA(p)->dfree = 0; @@ -2115,6 +2109,7 @@ rb_gc_call_finalizer_at_exit(void) p = deferred_final_list; deferred_final_list = 0; finalize_list(objspace, p); + mark_tbl(objspace, finalizer_table, 0); st_foreach(finalizer_table, chain_finalized_object, (st_data_t)&deferred_final_list); } while (deferred_final_list); |