遠藤と申します。

aaa, aab, aac, ...(300 個くらい)..., *zzz = 1 という多重代入を
GC.stress=true かつ Fiber の中で実行すると落ちます。


$ ./ruby -e '
a,s=[],"aaa"
300.times { a<<s; s=s.succ }
puts <<END
GC.stress=true
Fiber.new do
  #{ a.join(",") },*zzz=1
end.resume
END
' > t.rb

$ ./ruby t.rb
t.rb:3: -- control frame ----------
c:0003 p:0006 s:0607 b:0305 l:00110c d:000304 BLOCK  t.rb:3
c:0002 p:---- s:0003 b:0003 l:000002 d:000002 FINISH :(null)
c:0001 p:---- s:0001 b:-001 l:000000 d:000000 ------ :(null)
---------------------------
-- backtrace of native function call (Use addr2line) --
0x80ebbf5
0x8109e93
0x8109f5b
0x80bcdd0
0xffffe440
0x8062c4f
0x806386b
0x80634c1
0x80634c1
0x80634c1
(snip)
0x80634c1
0x80634c1
0x80e19bd
0x8063538
0x80e18b1
0x80c13f0
0x80e1ca0
0x8063538
0x8063d33
0x8064545
0x80f3a2c
0x80f3d8a
0x80f5194
0x80f573c
0x80e6026
0x80ea4b4
0x80e3707
0x80e3e37
0x80f1148
0x805a6e3
0x805e510
0x8058220
0xb7d6dea8
0x8058141
-------------------------------------------------------
[BUG] Segmentation fault
ruby 1.9.0 (2007-12-13) [i686-linux]

アボートしました



原因は、vm_expandarray 内で rb_ary_to_ary を実行する前に sp を
ずらしているため、rb_ary_to_ary 内で GC が発生したとき、無効な
VALUE 値を mark してしまっているのだと思います。

Index: insnhelper.ci
===================================================================
--- insnhelper.ci	(revision 14213)
+++ insnhelper.ci	(working copy)
@@ -1347,12 +1347,12 @@
     volatile VALUE tmp_ary;
     int len;

-    cfp->sp += space_size;
-
     if (TYPE(ary) != T_ARRAY) {
 	ary = rb_ary_to_ary(ary);
     }

+    cfp->sp += space_size;
+
     tmp_ary = ary;
     ptr = RARRAY_PTR(ary);
     len = RARRAY_LEN(ary);

-- 
Yusuke ENDOH <mame / tsg.ne.jp>