From: patamanta@... Date: 2010-03-19T00:34:16+09:00 Subject: [ruby-dev:40699] Re: Ruby+SWIGでGC実行時に不正なマークをしている可能性があります 金田と申します。 下記の件ですがSWIGが生成するコードが不適切なのが原因の可能性があります。 SWIG Version 1.3.36 で添付ファイルの.iファイルから external_lib_wrap.cxx を生成すると 次のようなコードが 3890行目付近で生成されます。 VALUE obj = rb_ary_new2((int)size); int i = 0; for (const_iterator it = seq.begin(); it != seq.end(); ++it, ++i) { RARRAY_PTR(obj)[i] = swig::from< value_type >(*it); } RARRAY_LEN(obj) = size; rb_obj_freeze(obj); // treat as immutable result この処理は不適切です。 swig::from< value_type >(*it) でオブジェクトを 生成した際にGCが発生した場合、 obj の配列に格納済みのオブジェクトが GC で回収されてしまい不正となります。これは上記の処理では配列に 格納済みのオブジェクトが GC の mark対象とならないためです。 実際、この処理の前後に rb_gc_disable(); / rb_gc_enable(); を加えると 正常に処理が進みます。 もしくは RARRAY_PTR(obj)[i] = swig::from< value_type >(*it); の代わりに rb_ary_push(obj, swig::from< value_type >(*it)); を使ってももよいようです。 この場合 RARRAY_LEN(obj) = size; は削除しておく必要があります。 rb_gc_disable() や rb_ary_pushを使うよりは 最初に全て Qnil を配列に埋めてからオブジェクトを 格納した方が高速化もしれませんがこちらは試していません。 ----- Original Message ----- 送信者: Toshio Maki 宛先: ruby-dev@ruby-lang.org 日付:Thursday, March, 18, 2010, 02:57 PM 件名: [ruby-dev:40694] Ruby+SWIGでGC実行時に不正なマークをしている可能性があります >  初めまして。牧と申します。 > >  Ruby+SWIGを用いたプログラムでSIGSEGVが発生するので、原因を調査していた > のですが、gc_mark付近が怪しいので、報告させていただきます。 > > 現象 >  SWIGでSTLをラップした関数を自動生成し、Ruby側から呼び出したときに、 > SIGSEGVやNotImplementedErrorが発生します。 > > その1 >  SIGSEGVでアボートするケース。コアのスタックトレースは以下の通りです。 > > #0 0x000000337b030265 in raise () from /lib64/libc.so.6 > #1 0x000000337b031d10 in abort () from /lib64/libc.so.6 > #2 0x0000000000499878 in rb_bug (fmt=0x4b5f0d "Segmentation fault") at error.c:213 > #3 0x00000000004706aa in sigsegv (sig=) at signal.c:634 > #4 > #5 st_lookup (table=0x0, key=3137, value=0x7fff3d254a40) at st.c:250 > #6 0x0000000000411595 in search_method (klass=47793957212960, id=3137, origin=0x7fff3d254 a78) at eval.c:486 > #7 0x0000000000411607 in rb_get_method_body (klassp=0x7fff3d254ac0, idp=0x7fff3d254ac8, n oexp=0x7fff3d254ad4) at eval.c:507 > #8 0x000000000041c205 in rb_call (klass=47793957212960, recv=47793957213000, mid=3137, ar gc=0, argv=0x0, scope=1, self=6) at eval.c:6150 > #9 0x000000000041c7e8 in vafuncall (recv=47793957213000, mid=3137, n=7219792, ar=) at eval.c:6253 > #10 0x000000000041ca73 in rb_funcall (recv=0, mid=3137, n=1025854016) at eval.c:6270 > > その2 >  NotImplementedErrorが発生する。(添付のソースは以下の現象が発生) > > call_external_lib.rb:6:in `p': method `inspect' called on terminated object (0x2b1a83bc88d 8) (NotImplementedError) > from call_external_lib.rb:6 > from call_external_lib.rb:5:in `each' > from call_external_lib.rb:5 > from call_external_lib.rb:4:in `each' > from call_external_lib.rb:4 > > >  再現環境 >  gcc バージョン 4.1.2 20080704 (Red Hat 4.1.2-46) >  ruby 1.8.7 (2009-12-24 patchlevel 249) [x86_64-linux] >  SWIG Version 1.3.29 Compiled with g++ [i686-redhat-linux-gnu] > >  また環境依存のせいか、発生しないケースもあります。 > > ・再現した >  Red Hat Enterprise Linux Server release 5.4 (Tikanga) x86_64 >  Ubuntu 09-10 32bit > > ・再現しない >  CentOS release 5.4 (Final) 32bit > > > 原因? >  C側で生成したvectorのポインタをData_Wrap_structでRubyのVALUEに変換する > 際に、rb_newobjがGCを呼ぶので、その際に呼ばれたgc_markやmark_tblが何かやっ > ているのではないかと考えています。ruby側でGC.disableやC側でrb_gc_disable > を実行しておくと発生しません。 > > 類似? >  同じ現象かどうかは分かりませんが、以前にも似たような報告があったようで > す。 > Segmentation fault in garbage collector ruby 1.8.7 (2008-10-31 revision 0) [x86_64-linux] >  http://redmine.ruby-lang.org/issues/show/706 > > /***************************************************/ > 日立ソフトウェアエンジニアリング株式会社 > 技術開発本部 Rubyセンタ > > 牧 俊男 > /***************************************************/ >