From: SASADA Koichi Date: 2010-10-13T14:13:46+09:00 Subject: [ruby-dev:42369] [BUG: trunk] Lazy sweep and ObjectSpace.each_object  ささだです。  Lazy sweep 中に ObjectSpace.each_object(相当)を行うと、SEGV するの で、下記のようなパッチを作成しました。 # 32bit 環境の test-all で、最近 sdbm で SEGV してたのは多分これが問題。 # ObjectSpace.each_object を使っているので。  推測ですが、下記のような原因ではないかと思います。 (1) GC mark 終了時、オブジェクト o1 と、そこから参照される o2 が mark されず、sweep 対象になる (2) lazy sweep により、o2 が回収される (3) ObjectSpace.each_object により、o1 へアクセスする (4) o1 から o2 を参照しようとして SEGV  解決策として、中田さんに ObjectSpace.each_object に相当する関数 rb_objspace_each_objects を実行する前に sweep を完全に終了させる、という 方法を教えてもらいました。  バグの確認コードとパッチをお送りします。もし、適当でしたら取り込んで頂 けると幸いです。 確認コード: loop{ cls = (0..10_000).map{Class.new} cls.each{|c| c.new} ObjectSpace.each_object{|e| e.object_id; ''} } パッチ: Index: gc.c =================================================================== --- gc.c (revision 29471) +++ gc.c (working copy) @@ -2040,6 +2040,17 @@ return FALSE; } +static void +rest_sweep(rb_objspace_t *objspace) +{ + if (objspace->heap.sweep_slots) { + while (objspace->heap.sweep_slots) { + lazy_sweep(objspace); + } + after_gc_sweep(objspace); + } +} + static void gc_marks(rb_objspace_t *objspace); static int @@ -2536,6 +2547,8 @@ rb_objspace_t *objspace = &rb_objspace; volatile VALUE v; + rest_sweep(objspace); + i = 0; while (i < heaps_used) { while (0 < i && (uintptr_t)membase < (uintptr_t)objspace->heap.sorted[i-1].slot->membase) -- // SASADA Koichi at atdot dot net