Bug #3940

Lazy sweep and ObjectSpace.each_object

Added by Koichi Sasada over 3 years ago. Updated almost 3 years ago.

[ruby-dev:42369]
Status:Closed
Priority:High
Assignee:Narihiro Nakamura
Category:core
Target version:1.9.3
ruby -v:ruby 1.9.3dev (2010-10-13 trunk 29477) Backport:

Description

=begin
 ささだです。

 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.eachobject に相当する関数
rb
objspaceeachobjects を実行する前に sweep を完全に終了させる、という
方法を教えてもらいました。

 バグの確認コードとパッチをお送りします。もし、適当でしたら取り込んで頂
けると幸いです。

確認コード:

loop{
cls = (0..10000).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
+restsweep(rbobjspacet *objspace)
+{
+ if (objspace->heap.sweep
slots) {
+ while (objspace->heap.sweepslots) {
+ lazy
sweep(objspace);
+ }
+ aftergcsweep(objspace);
+ }
+}
+
static void gcmarks(rbobjspace_t *objspace);

static int
@@ -2536,6 +2547,8 @@
rbobjspacet *objspace = &rb_objspace;
volatile VALUE v;

  • restsweep(objspace);
    +
    i = 0;
    while (i < heaps
    used) {
    while (0 < i && (uintptrt)membase <
    (uintptr
    t)objspace->heap.sorted[i-1].slot->membase)

    // SASADA Koichi at atdot dot net
    =end

Associated revisions

Revision 29543
Added by nari over 3 years ago

  • gc.c (rbobjspaceeachobjects): don't lazy sweep in rbobjspaceeachobjects. [Bug #3940]

History

#1 Updated by Usaku NAKAMURA over 3 years ago

  • Category set to core
  • Status changed from Open to Assigned
  • Assignee set to Narihiro Nakamura
  • Priority changed from Low to High
  • Target version set to 1.9.3
  • ruby -v set to ruby 1.9.3dev (2010-10-13 trunk 29477)

=begin

=end

#2 Updated by Yukihiro Matsumoto over 3 years ago

=begin
まつもと ゆきひろです

In message "Re: [BUG: trunk] Lazy sweep and ObjectSpace.each_object"
on Wed, 13 Oct 2010 14:13:46 +0900, SASADA Koichi ko1@atdot.net writes:

| 解決策として、中田さんに ObjectSpace.eachobject に相当する関数
|rb
objspaceeachobjects を実行する前に sweep を完全に終了させる、という
|方法を教えてもらいました。

オブジェクトがsweep対象かどうかはわかるはずなんだから、sweep
されるはずのものはeach_objectの対象にしない手もあるんじゃな
いの? なんか勘違いしてる?

=end

#3 Updated by Koichi Sasada over 3 years ago

=begin
 ささだです。

(2010/10/14 2:34), Yukihiro Matsumoto wrote:

| 解決策として、中田さんに ObjectSpace.eachobject に相当する関数
|rb
objspaceeachobjects を実行する前に sweep を完全に終了させる、という
|方法を教えてもらいました。

オブジェクトがsweep対象かどうかはわかるはずなんだから、sweep
されるはずのものはeach_objectの対象にしない手もあるんじゃな
いの? なんか勘違いしてる?

 手もあると思います。

 ただ、 "rbobjspaceeach_objects()" の仕様上、slot を callback にその
まま渡すようにしているため、free / sweep 対象かは、callback 先で確認しな
ければなりません。free オブジェクトかどうかは、

flag が 0 かどうか

で見ることが出来ますが、sweep 対象(実質 free)であるかどうかは、

slot が sweep_slots かつ、
mark されていないか

を確認しなければなりません。callback に sweepslots かどうかを入れるのも
大変だし、そもそも rb
objspaceeachobjects() なんて使われるのはレアケー
スだし、まー全部やっちゃえばいいか、という感じです。

 と、今気づきましたが、rbobjspaceeach_objects() の callback で GC が
起きても同じ問題がありますね。callback する前で sweep を完了するように変
更しても、結局問題は残るし。どうしようかな。

 上記 check を行う rbobjspacelive_p(VALUE) みたいなのを用意して、これ
を使うようにしてもらう、とか?

--
// SASADA Koichi at atdot dot net

=end

#4 Updated by Keiju Ishitsuka over 3 years ago

=begin
けいじゅ@いしつかです.

In the message: " [BUG: trunk] Lazy
sweep and ObjectSpace.each_object", on Oct/13 14:13(JST) SASADA Koichi
writes:

 ささだです。

 Lazy sweep 中に ObjectSpace.each_object(相当)を行うと、SEGV するの
で、下記のようなパッチを作成しました。

ちょっとお聞きしたいんですけど, この問題って, どの辺りのバージョンから
入っています?

それと, 1.9.2での話なんですが, finalizerを指定している場合プロセス終了
時にSEGVすることがあるんですが, これと関係ありますでしょうか?

__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: keiju@ishitsuka.com <<---

=end

#5 Updated by Koichi Sasada over 3 years ago

=begin
 ささだです。

(2010/10/15 9:16), 石塚圭樹 wrote:

 Lazy sweep 中に ObjectSpace.each_object(相当)を行うと、SEGV するの
で、下記のようなパッチを作成しました。
ちょっとお聞きしたいんですけど, この問題って, どの辺りのバージョンから
入っています?

それと, 1.9.2での話なんですが, finalizerを指定している場合プロセス終了
時にSEGVすることがあるんですが, これと関係ありますでしょうか?

 1.9.3 以降です。

 1.9.2 のほうは、別の問題かと思います。

--
// SASADA Koichi at atdot dot net

=end

#6 Updated by Keiju Ishitsuka over 3 years ago

=begin
けいじゅ@いしつかです.

In the message: " Re: [BUG: trunk]
Lazy sweep and ObjectSpace.each_object", on Oct/15 17:26(JST) SASADA
Koichi writes:

 ささだです。

ちょっとお聞きしたいんですけど, この問題って, どの辺りのバージョンから
入っています?

 1.9.3 以降です。

そうですか, 残念.

ところで, 添付のようなエラーが出てSEGVしちゃうんですけど, 原因が何か分
かります?

何をやっているかというと, 親プロセスから子プロセスをforkしていて, 子側
がSEGVしています.

親側では, threadとかmutexを使っていて色々と非同期処理をしています.
fork後, 子側でそのthreadがGCされるときに発生しているみたいなんですが...

非同期処理をしながらforkするところに無理があるって話もありそうなんです
が...

それと, このバックトレースではeach_object中に発生していますが, その前
に GC.start を入れると, そこで発生します.

-- ここから
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:94: [BUG] threadfree: lockingmutex must be NULL (0x87fd5f0:138337388)
ruby 1.9.1p430 (2010-08-16 revision 28998) [i686-linux]

-- control frame ----------
c:0015 p:0015 s:0049 b:0048 l:000031 d:000047 BLOCK /var/projects/fairy/fairy/lib/fairy/share/base-app.rb:94
c:0014 p:---- s:0045 b:0045 l:000044 d:000044 FINISH
c:0013 p:---- s:0043 b:0043 l:000042 d:000042 CFUNC :each_object
c:0012 p:0022 s:0039 b:0039 l:000031 d:000038 BLOCK /var/projects/fairy/fairy/lib/fairy/share/base-app.rb:92
c:0011 p:---- s:0037 b:0037 l:000036 d:000036 FINISH
c:0010 p:---- s:0035 b:0035 l:000034 d:000034 CFUNC :fork
c:0009 p:0035 s:0032 b:0032 l:000031 d:000031 METHOD /var/projects/fairy/fairy/lib/fairy/share/base-app.rb:91
c:0008 p:0016 s:0027 b:0027 l:000026 d:000026 METHOD /var/projects/fairy/fairy/lib/fairy/share/base-app.rb:18
c:0007 p:0080 s:0022 b:0022 l:000015 d:000021 BLOCK /var/projects/fairy/fairy/lib/fairy/master.rb:112
c:0006 p:0019 s:0019 b:0019 l:000018 d:000018 METHOD internal:prelude:8
c:0005 p:0012 s:0016 b:0016 l:000015 d:000015 METHOD /var/projects/fairy/fairy/lib/fairy/master.rb:110
c:0004 p:0145 s:0013 b:0013 l:000012 d:000012 METHOD /var/projects/fairy/lib/deep-connect/evaluator.rb:32
c:0003 p:0064 s:0006 b:0006 l:0023fc d:000005 BLOCK /var/projects/fairy/lib/deep-connect/session.rb:155
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
c:0001 p:---- s:0002 b:0002 l:000001 d:000001 CONT#0 controller.rb[186] Controller[0]#block (2 levels) in terminate: TERMINATE: #2.5.3
CONT#0 controller.rb[191] Controller[0]#block (2 levels) in terminate: TERMINATE: #2.6
CONT#0 controller.rb[166] Controller[0]#block (2 levels) in terminate: TERMINATE: #2.3
CONT#0 controller.rb[168] Controller[0]#block (2 levels) in terminate: TERMINATE: #2.4
TOP


-- Ruby level backtrace information-----------------------------------------
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:94:in block (2 levels) in start_subcommand'
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:92:in
eachobject'
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:92:in block in start_subcommand'
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:91:in
fork'
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:91:in start_subcommand'
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:18:in
start
subcommand'
/var/projects/fairy/fairy/lib/fairy/master.rb:112:in block in assgin_controller'
<internal:prelude>:8:in
synchronize'
[M] master.rb[80] Master#when_disconnected: MASTER: disconnected: Start terminationcts/fairy/lib/deep-connect/evaluator.rb:32:in evaluate_request'
/var/projects/fairy/lib/deep-connect/session.rb:155:in
block in receive'

-- C level backtrace information -------------------------------------------
0x8157b71 fairy master (rbvmbugreport+0xa1) [0x8157b71]
0x8193156 fairy master [0x8193156]
0x8193208 fairy master (rbbug+0x28) [0x8193208]
0x814311d fairy master [0x814311d]
0x8064e9e fairy master [0x8064e9e]
0x8065339 fairy master (rb
gcfinalizedeferred+0x59) [0x8065339]
0x815c2ad fairy master [0x815c2ad]
0x8155fe9 fairy master [0x8155fe9]
0x8148ddb fairy master [0x8148ddb]
0x814f644 fairy master [0x814f644]
0x8150a7f fairy master (rb_yield+0x4f) [0x8150a7f]
0x80682e6 fairy master [0x80682e6]
0x8143f7d fairy master [0x8143f7d]
0x81440a4 fairy master [0x81440a4]
0x8155f54 fairy master [0x8155f54]
0x8148ddb fairy master [0x8148ddb]

__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: keiju@ishitsuka.com <<---

=end

#7 Updated by Koichi Sasada over 3 years ago

=begin
 ささだです。

(2010/10/15 12:40), 石塚圭樹 wrote:

ところで, 添付のようなエラーが出てSEGVしちゃうんですけど, 原因が何か分
かります?

何をやっているかというと, 親プロセスから子プロセスをforkしていて, 子側
がSEGVしています.

親側では, threadとかmutexを使っていて色々と非同期処理をしています.
fork後, 子側でそのthreadがGCされるときに発生しているみたいなんですが...

非同期処理をしながらforkするところに無理があるって話もありそうなんです
が...

それと, このバックトレースではeach_object中に発生していますが, その前
に GC.start を入れると, そこで発生します.

-- ここから
/var/projects/fairy/fairy/lib/fairy/share/base-app.rb:94: [BUG] threadfree: lockingmutex must be NULL (0x87fd5f0:138337388)
ruby 1.9.1p430 (2010-08-16 revision 28998) [i686-linux]

 さすがにこれだけでは...、と思ったけど、fork した直後に locking_mutex
を空にする処理を走らせているのに、それが間に合ってない感じですかね。

 ファイナライザで何をやっているか、などを併せて最小ケースを貰えると良い
かもしれません。

--
// SASADA Koichi at atdot dot net

=end

#8 Updated by Narihiro Nakamura over 3 years ago

=begin
nariです。

2010年10月14日19:13 SASADA Koichi ko1@atdot.net:

 ささだです。

(2010/10/14 2:34), Yukihiro Matsumoto wrote:

| 解決策として、中田さんに ObjectSpace.eachobject に相当する関数
|rb
objspaceeachobjects を実行する前に sweep を完全に終了させる、という
|方法を教えてもらいました。

オブジェクトがsweep対象かどうかはわかるはずなんだから、sweep
されるはずのものはeach_objectの対象にしない手もあるんじゃな
いの? なんか勘違いしてる?

 手もあると思います。

ただ、 "rbobjspaceeach_objects()" の仕様上、slot を callback にその
まま渡すようにしているため、free / sweep 対象かは、callback 先で確認しな
ければなりません。free オブジェクトかどうかは、

   flag が 0 かどうか

で見ることが出来ますが、sweep 対象(実質 free)であるかどうかは、

   slot が sweep_slots かつ、
   mark されていないか

を確認しなければなりません。callback に sweepslots かどうかを入れるのも
大変だし、そもそも rb
objspaceeachobjects() なんて使われるのはレアケー
スだし、まー全部やっちゃえばいいか、という感じです。

と、今気づきましたが、rbobjspaceeach_objects() の callback で GC が
起きても同じ問題がありますね。callback する前で sweep を完了するように変
更しても、結局問題は残るし。どうしようかな。

上記 check を行う rbobjspacelive_p(VALUE) みたいなのを用意して、これ
を使うようにしてもらう、とか?

// SASADA Koichi at atdot dot net

rbobjspaceeachobjects() の実行前には sweep を完全に終了させることに
して、実行中は rb
gc_disable() して、実行後に元に戻すようにどうかなと思った
のですが、いかがでしょうか?

--
Narihiro Nakamura (nari)

=end

#9 Updated by Koichi Sasada over 3 years ago

=begin
 ささだです。

(2010/10/18 5:01), Narihiro Nakamura wrote:

rbobjspaceeachobjects() の実行前には sweep を完全に終了させることに
して、実行中は rb
gc_disable() して、実行後に元に戻すようにどうかなと思った
のですが、いかがでしょうか?

 GC.enable で回避できてしまう(SEGV するパスが出来てしまう)のでまずい
のではないでしょうか。

 少し考えてみたのですが、例えば、Lazy sweep 禁止フラグ(eager に sweep
する)を設けるのはどうでしょうか。Ruby 側からは触らせないフラグにすれ
ば、SEGV する危険は防ぐことが出来るのではないかと。

--
// SASADA Koichi at atdot dot net

=end

#10 Updated by Narihiro Nakamura over 3 years ago

=begin
nariです。

2010年10月18日13:15 SASADA Koichi ko1@atdot.net:

 ささだです。

(2010/10/18 5:01), Narihiro Nakamura wrote:

rbobjspaceeachobjects() の実行前には sweep を完全に終了させることに
して、実行中は rb
gc_disable() して、実行後に元に戻すようにどうかなと思った
のですが、いかがでしょうか?

 GC.enable で回避できてしまう(SEGV するパスが出来てしまう)のでまずい
のではないでしょうか。

そうですね。

少し考えてみたのですが、例えば、Lazy sweep 禁止フラグ(eager に sweep
する)を設けるのはどうでしょうか。Ruby 側からは触らせないフラグにすれ
ば、SEGV する危険は防ぐことが出来るのではないかと。

なるほど。そのように作ってみます。

--
Narihiro Nakamura (nari)

=end

#11 Updated by Narihiro Nakamura over 3 years ago

=begin
nariです。

Lazy sweep 禁止フラグを作りました。
反対がなければコミットしたいと思います。

callbackの途中でGCが呼ばれてSEGVを起こすようなコードを作成し、通ることを確認しました。
make checkも通ることを確認しています。

確認コード:

loop {
GC.disable
10.times do
a = []
1000.times{ a << "" }
a.dup
end
GC.enable
ObjectSpace.eachobject(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 rbobjspace {
} heap;
struct {
int dont
gc;
+ int dontlazysweep;
int duringgc;
} flags;
struct {
@@ -2040,6 +2041,17 @@ lazy
sweep(rbobjspacet *objspace)
return FALSE;
}

+static void
+restsweep(rbobjspacet *objspace)
+{
+ if (objspace->heap.sweep
slots) {
+ while (objspace->heap.sweepslots) {
+ lazy
sweep(objspace);
+ }
+ aftergcsweep(objspace);
+ }
+}
+
static void gcmarks(rbobjspace_t *objspace);

static int
@@ -2047,6 +2059,9 @@ gclazysweep(rbobjspacet *objspace)
{
int res;

  • if (objspace->flags.dontlazysweep)
  •    return garbage_collect(objspace);
    

    +
    INITGCPROF_PARAMS;

    if (!readytogc(objspace)) return TRUE;
    @@ -2536,6 +2551,9 @@ rbobjspaceeachobjects(int (*callback)(void
    *vstart, void *vend,
    rb
    objspacet *objspace = &rbobjspace;
    volatile VALUE v;

  • rest_sweep(objspace);

  • objspace->flags.dontlazysweep = TRUE;
    +
    i = 0;
    while (i < heapsused) {
    while (0 < i && (uintptr
    t)membase <
    (uintptrt)objspace->heap.sorted[i-1].slot->membase)
    @@ -2562,6 +2580,7 @@ rb
    objspaceeachobjects(int (*callback)(void
    *vstart, void *vend,
    }
    }

  • objspace->flags.dontlazysweep = FALSE;
    return;
    }

    Narihiro Nakamura (nari)

=end

#12 Updated by Koichi Sasada over 3 years ago

=begin
 ささだです。

(2010/10/18 7:14), Narihiro Nakamura wrote:

Lazy sweep 禁止フラグを作りました。
反対がなければコミットしたいと思います。

callbackの途中でGCが呼ばれてSEGVを起こすようなコードを作成し、通ることを確認しました。
make checkも通ることを確認しています。

 これだと、例えば例外が出た場合、dontlazysweep が TRUE のままになって
しまうような気がします。ensure で囲まないと。

# 余談

 ちょっと関係ないですが、gclazysweep() という関数は、下記の挙動だと思
うのですが;

・もし、遅延した slot があれば、sweep をする
 これで、freelist が NULL でなければ、ここで終わり
・GC を開始(mark)
・遅延 sweep をして、結果を返す

sweep という関数で mark までしちゃうのはいいでしょうか。

 あまり、対案はないのですが、なんとなく、garbagecollect() を 今の
gc
lazysweep() として、今の garbagecollect() を、
garbagecollecteager() みたいにしてしまうのはどうだろう、と思いました。

--
// SASADA Koichi at atdot dot net

=end

#13 Updated by Narihiro Nakamura over 3 years ago

=begin
nariです。

 これだと、例えば例外が出た場合、dontlazysweep が TRUE のままになって
しまうような気がします。ensure で囲まないと。

ぉぉ、そうですね…。ご指摘ありがとうございます。
そのようなパッチを作ってみました。本メールの一番最後に貼り付けておきます。

余談

ちょっと関係ないですが、gclazysweep() という関数は、下記の挙動だと思
うのですが;

・もし、遅延した slot があれば、sweep をする
これで、freelist が NULL でなければ、ここで終わり
・GC を開始(mark)
・遅延 sweep をして、結果を返す

sweep という関数で mark までしちゃうのはいいでしょうか。

なるほど。
関数名にgc_というプレフィクスが付いているので、マークしてもいいのかなと
か、そういう言い訳を思いついたのですがやっぱりダメですね。

あまり、対案はないのですが、なんとなく、garbagecollect() を 今の
gc
lazysweep() として、今の garbagecollect() を、
garbagecollecteager() みたいにしてしまうのはどうだろう、と思いました。

garbagecollecteager() よりも garbagecollectfull() の方が馴染み
があるのかなと思いました。こちらの方も暇を見つけて直しておきます。

パッチ:
diff --git a/gc.c b/gc.c
index b011f4a..ad49fd5 100644
--- a/gc.c
+++ b/gc.c
@@ -332,6 +332,7 @@ typedef struct rbobjspace {
} heap;
struct {
int dont
gc;
+ int dontlazysweep;
int duringgc;
} flags;
struct {
@@ -2040,6 +2041,17 @@ lazy
sweep(rbobjspacet *objspace)
return FALSE;
}

+static void
+restsweep(rbobjspacet *objspace)
+{
+ if (objspace->heap.sweep
slots) {
+ while (objspace->heap.sweepslots) {
+ lazy
sweep(objspace);
+ }
+ aftergcsweep(objspace);
+ }
+}
+
static void gcmarks(rbobjspace_t *objspace);

static int
@@ -2047,6 +2059,9 @@ gclazysweep(rbobjspacet *objspace)
{
int res;

  • if (objspace->flags.dontlazysweep)
  •    return garbage_collect(objspace);
    

    +
    INITGCPROF_PARAMS;

    if (!readytogc(objspace)) return TRUE;
    @@ -2489,6 +2504,55 @@ Initheap(void)
    init
    heap(&rb_objspace);
    }

    +
    +static VALUE
    +lazysweepenable(void)
    +{

  • rbobjspacet *objspace = &rb_objspace;
    +

  • objspace->flags.dontlazysweep = FALSE;

  • return Qnil;
    +}
    +
    +static VALUE
    +objspaceeachobjects(VALUE arg)
    +{

  • size_t i;

  • RVALUE *membase = 0;

  • RVALUE *pstart, *pend;

  • rbobjspacet *objspace = &rb_objspace;

  • VALUE *args = (VALUE *)arg;

  • volatile VALUE v;
    +

  • i = 0;

  • while (i < heaps_used) {

  • while (0 < i && (uintptrt)membase <
    (uintptr
    t)objspace->heap.sorted[i-1].slot->membase)

  •  i--;
    
  • while (i < heapsused &&
    (uintptr
    t)objspace->heap.sorted[i].slot->membase <=
    (uintptr_t)membase )

  •  i++;
    
  • if (heaps_used <= i)

  • break;

  • membase = objspace->heap.sorted[i].slot->membase;
    +

  • pstart = objspace->heap.sorted[i].slot->slot;

  • pend = pstart + objspace->heap.sorted[i].slot->limit;
    +

  • for (; pstart != pend; pstart++) {

  •  if (pstart->as.basic.flags) {
    
  •  v = (VALUE)pstart; /* acquire to save this object */
    
  •  break;
    
  •  }
    
  • }

  • if (pstart != pend) {

  •  if ((*(int (*)(void *, void *, size_t, void *))args[0])(pstart,
    

    pend, sizeof(RVALUE), (void *)args[1])) {

  •  return;
    
  •  }
    
  • }

  • }
    +

  • return Qnil;
    +}
    +
    /*

    • rbobjspaceeach_objects() is special C API to walk through
    • Ruby object space. This C API is too difficult to use it. @@ -2530,39 +2594,15 @@ rbobjspaceeachobjects(int (*callback)(void *vstart, void *vend, sizet stride, void *d), void *data) {
  • size_t i;

  • RVALUE *membase = 0;

  • RVALUE *pstart, *pend;

  • VALUE args[2];
    rbobjspacet *objspace = &rb_objspace;

  • volatile VALUE v;

  • i = 0;

  • while (i < heaps_used) {

  • while (0 < i && (uintptrt)membase <
    (uintptr
    t)objspace->heap.sorted[i-1].slot->membase)

  •  i--;
    
  • while (i < heapsused &&
    (uintptr
    t)objspace->heap.sorted[i].slot->membase <=
    (uintptr_t)membase )

  •  i++;
    
  • if (heaps_used <= i)

  • break;

  • membase = objspace->heap.sorted[i].slot->membase;

  • pstart = objspace->heap.sorted[i].slot->slot;

  • pend = pstart + objspace->heap.sorted[i].slot->limit;

  • for (; pstart != pend; pstart++) {

  •  if (pstart->as.basic.flags) {
    
  •  v = (VALUE)pstart; /* acquire to save this object */
    
  •  break;
    
  •  }
    
  • }

  • if (pstart != pend) {

  •  if ((*callback)(pstart, pend, sizeof(RVALUE), data)) {
    
  •  return;
    
  •  }
    
  • }

  • }

  • rest_sweep(objspace);

  • objspace->flags.dontlazysweep = TRUE;

  • return;

  • args[0] = (VALUE)callback;

  • args[1] = (VALUE)data;

  • rbensure(objspaceeachobjects, (VALUE)args, lazysweep_enable, Qnil);
    }

    struct oseachstruct {

    Narihiro Nakamura (nari)

=end

#14 Updated by Anonymous over 3 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r29543.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF