From: Narihiro Nakamura Date: 2010-10-18T15:14:47+09:00 Subject: [ruby-dev:42417] Re: [BUG: trunk] Lazy sweep and ObjectSpace.each_object nariです。 Lazy sweep 禁止フラグを作りました。 反対がなければコミットしたいと思います。 callbackの途中でGCが呼ばれてSEGVを起こすようなコードを作成し、通ることを確認しました。 make checkも通ることを確認しています。 確認コード: loop { GC.disable 10.times do a = [] 1000.times{ a << "" } a.dup end GC.enable ObjectSpace.each_object(Array) do |a| a.map(&:object_id) 10000.times{''.dup} end } パッチ: diff --git a/gc.c b/gc.c index b011f4a..a9a4560 100644 --- a/gc.c +++ b/gc.c @@ -332,6 +332,7 @@ typedef struct rb_objspace { } heap; struct { int dont_gc; + int dont_lazy_sweep; int during_gc; } flags; struct { @@ -2040,6 +2041,17 @@ lazy_sweep(rb_objspace_t *objspace) 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 @@ -2047,6 +2059,9 @@ gc_lazy_sweep(rb_objspace_t *objspace) { int res; + if (objspace->flags.dont_lazy_sweep) + return garbage_collect(objspace); + INIT_GC_PROF_PARAMS; if (!ready_to_gc(objspace)) return TRUE; @@ -2536,6 +2551,9 @@ rb_objspace_each_objects(int (*callback)(void *vstart, void *vend, rb_objspace_t *objspace = &rb_objspace; volatile VALUE v; + rest_sweep(objspace); + objspace->flags.dont_lazy_sweep = TRUE; + i = 0; while (i < heaps_used) { while (0 < i && (uintptr_t)membase < (uintptr_t)objspace->heap.sorted[i-1].slot->membase) @@ -2562,6 +2580,7 @@ rb_objspace_each_objects(int (*callback)(void *vstart, void *vend, } } + objspace->flags.dont_lazy_sweep = FALSE; return; } -- Narihiro Nakamura (nari)