From: "H.Yamamoto" Date: 2005-12-19T16:47:42+09:00 Subject: [ruby-dev:28054] Re: ruby 1.8 dumps core 山本です。 >> 田中さんの提唱する GC.always メソッド版があれば便利な気がします。 >> 現状では、test_yaml が実行される前にすごく長い時間がかかります。 > >ここのところ RUBY_ALWAYS_GC を実際に使うほうにかまけていて、 >メソッドの提案のほうを放置してましたが、[ruby-dev:28007] の >GC.stress=bool を入れるのはどうですかね。 賛成します。手元で類似のパッチを gc.c に入れてデバッグしたところ、 さっそくひとつ見つかりました。 # syck_emitter_reset で bonus->port が GC から保護されていないために # 解放されてしまうバグを修正。(手元のパッチなので HEAD には当たりません) Index: E:/ruby-cvs/ruby/ext/syck/rubyext.c =================================================================== --- E:/ruby-cvs/ruby/ext/syck/rubyext.c (revision 12) +++ E:/ruby-cvs/ruby/ext/syck/rubyext.c (revision 13) @@ -1974,16 +1974,14 @@ { VALUE options, tmp; SyckEmitter *emitter; - struct emitter_xtra *bonus; - volatile VALUE hash; /* protect from GC */ + struct emitter_xtra bonus; /* put on stack: protect member from GC */ Data_Get_Struct(self, SyckEmitter, emitter); S_FREE( emitter->bonus ); - bonus = S_ALLOC_N( struct emitter_xtra, 1 ); - bonus->oid = Qnil; - bonus->port = rb_str_new2( "" ); - bonus->data = hash = rb_hash_new(); + bonus.oid = Qnil; + bonus.port = rb_str_new2( "" ); + bonus.data = rb_hash_new(); if (rb_scan_args(argc, argv, "01", &options) == 0) { @@ -1992,20 +1990,21 @@ } else if ( !NIL_P(tmp = rb_check_string_type(options)) ) { - bonus->port = tmp; + bonus.port = tmp; } else if ( rb_respond_to( options, s_write ) ) { - bonus->port = options; + bonus.port = options; } else { Check_Type(options, T_HASH); rb_ivar_set(self, s_options, options); } - + emitter->headless = 1; - emitter->bonus = (void *)bonus; + emitter->bonus = S_ALLOC_N( struct emitter_xtra, 1 ); + *( struct emitter_xtra * )emitter->bonus = bonus; /* copy */ rb_ivar_set(self, s_level, INT2FIX(0)); rb_ivar_set(self, s_resolver, Qnil); return self;