[Ruby 1.9 - Bug #5350][Open] WeakRef で謎の NoMethodError

Issue #5350 has been reported by Makoto K…


Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Masaki M…

=begin
もう少しシンプルなコードにしてみました。
大量のWeakRefオブジェクトを生成すると、たまに正しく参照できない事があるようです。

require “weakref”

class Foo
def hoge; end
end

TIMES = 100000

A = []
TIMES.times do
A.push WeakRef.new Foo.new
end

A.each do |x|
begin
x.hoge
rescue WeakRef::RefError
end
end

正しく参照できなかった場合には、参照先のobject_idに20を足したFixnumが格納されたArrayや、caller、callerの一部と思われるStringなどが返ります。
=end

Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Shota F…

調査結果を報告します.

再現コードさらに短縮–

require “weakref”

class Foo
def initialize
@hoge = “fuga”
end

attr_reader :hoge
end

A = Array.new(5000) do
WeakRef.new Foo.new
end
GC.start

A.each do |x|
begin
x.hoge
rescue WeakRef::RefError
end
end

で,軽く調べまわって見たところ

WeakRefの@@finalの中の@@mutex.synchronizeで何故かdeadlock; recursive
locking例外が発生していました.
その所為でNoMethodErrorが起きるWeakRefの対象のオブジェクトがGCされていたとしても@@mutex.synchronize内の処理
で死亡したことがHashに書き込まれないため,WeakRef#weakref_alive?がtrueのままである感じです.

その場合はRangeErrorのほうでひっかかっても良いんじゃないのかなーと思うのですが,何故ファイナライザー中のsynchronizeで
recursive lockingになるのかを調査した所,rb_gc_finalize_deferred()
が関係してるのかなあ.うーん,よくわからない.

#20 0x0000000100059610 in rb_protect (proc=0x1000776c0
<run_single_final>, data=140734799778632, state=0x7fff5fbf9364) at
eval.c:709
#21 0x00000001000778db in run_finalizer (objspace=0x10081a800,
objid=4303620561, table=4303620400) at gc.c:2919
#22 0x0000000100077a2f in run_final (objspace=0x10081a800,
obj=4303620560) at gc.c:2947
#23 0x0000000100074844 in finalize_list (objspace=0x10081a800,
p=0x1008409d0) at gc.c:1937
#24 0x0000000100077a8c in finalize_deferred (objspace=0x10081a800) at
gc.c:2959
#25 0x0000000100077abd in rb_gc_finalize_deferred () at gc.c:2966
#26 0x000000010021370d in rb_threadptr_execute_interrupts_common
(th=0x100401db0) at thread.c:1311
#27 0x0000000100213858 in rb_threadptr_execute_interrupts
(th=0x100401db0) at thread.c:1335
#28 0x00000001001fc2f2 in vm_call_method (th=0x100401db0,
cfp=0x1005ffbe0, num=2, blockptr=0x0, flag=0, id=337, me=0x100449970,
recv=4303690840) at vm_insnhelper.c:676
#29 0x00000001001f39f8 in vm_exec_core (th=0x100401db0, initial=0) at
insns.def:1015
#30 0x000000010020a58b in vm_exec (th=0x100401db0) at vm.c:1220

Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Shota F…

a = Object.new
mutex = Mutex.new
ObjectSpace.define_finalizer(a) {
begin
mutex.synchronize { p “hi” }
rescue Exception => e
p e
end
}
mutex.synchronize {
a = nil
GC.stress = true
loop{ Object.new }
}

依存関係を無くしてみました.例外が発生しているのが確認できると思います.
(finalizer中の例外で終了することは無いみたいなので手動でrescue → Kernel#pしています.)

Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Shota F…

書こうと思っていて忘れたので追記.

どうやらmutex.synchronize中に何かの拍子でfinalizerが走り,そのfinalizerの中で同じmutexをsynchronizeすると起こってしまう模様.

そしてさっき古い再現しない再現コードを載せてしまいました… 再現するコードはこちらです.

a = Object.new
mutex = Mutex.new
ObjectSpace.define_finalizer(a) {
mutex.synchronize { p “ho” }
}
mutex.synchronize {
a = nil
GC.start
p “hi”
loop{ Object.new }
}


Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Masaki M…

File patch1.diff added
File patch2.diff added

@@final内でのMutex#synchronizeをやめる(添付のpatch1.diff)か、Mutexのロック前にGC.disableして解放後にenableする(patch2)かすれば再現しなくなりました。

Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Shota F…

両方共その場しのぎ,症状に対して防止策をしているだけだと思うのでこの2つのパッチはあまり根本的な解決にはならないと思います.

Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

(2011/09/23 17:44), Shota F. wrote:

test-allは通ったけど,はたしてこれでいいんだろうか.

良くないです.Mutex の保持と finalizer の実行は関係ありません.

このコードだけ見て反応しているので,元の問題は見ておらず,

そちらの解決策を示していなくてすみません.

ささだです.

(2011/09/23 18:47), Shota F. (sora_h) wrote:

mutex.synchronize { # (3)
locking" (thread.c:3555) が発生しています.

で,この問題に対する解決策は

  1. これは仕様という事にしてしまう
    → これが採用された場合,Glass_saga の GC.disable と GC.enable を挟む
    パッチ
    を取り込んで解決の方向?
  2. その他何らかの良い方法

問題のまとめをありがとうございます.

ファイナライザの実行は,何時起こるかわからないものなので,デッドロック
の可能性がある処理を行うのは,プログラムが悪い,ということになります.基
本的には,デッドロックを起こさないように書き直す必要がありますが,例えば
上記の場合では,mutex.trylock を利用することで回避することができます.

本質的に,何かしら他の対処が必要な話だろうか?

Issue #5350 has been updated by Shota F…

test-allは通ったけど,はたしてこれでいいんだろうか.

diff --git a/thread.c b/thread.c
index 10b73eb…de63c3a 100644
— a/thread.c
+++ b/thread.c
@@ -1307,7 +1307,7 @@ rb_threadptr_execute_interrupts_common(rb_thread_t
*th)
}
th->status = status;

  •   if (finalizer_interrupt) {
    
  •   if (finalizer_interrupt && !th->keeping_mutexes) {
          rb_gc_finalize_deferred();
      }
    

Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

ふむ.やはりダメか.そうだよなぁ.

元の問題がややこしくなっているので一旦まとめると,

a = Object.new
mutex = Mutex.new # finalizer と共有している mutex

ObjectSpace.define_finalizer(a) { # (1) a に対する finalizer
mutex.synchronize { p “ho” } # (2) ここでロックしようとするが, (3) と
# 同じスレッドなので ThreadError 例外発生
# (例外の発生は rescue で確認可能)
}
mutex.synchronize { # (3)
a = nil
GC.start
p “hi”
loop{ Object.new } # このループ中で (1) で定義した finalizer が呼ばれる
}

このようなサンプルコードを実行したときに (3) の mutex.synchronize 中に
オブジェクト a が解放された後,何らかのタイミングで a に対する finalizer
(1) が実行されると, (3) で mutex がロックされたまま同じスレッド (?) で
再び (2) で Mutex#lock を試みるため ThreadError “dead lock; recursive
locking” (thread.c:3555) が発生しています.

で,この問題に対する解決策は

  1. これは仕様という事にしてしまう
    → これが採用された場合,Glass_saga の GC.disable と GC.enable を挟む
    パッチ
    を取り込んで解決の方向?
  2. その他何らかの良い方法

かなぁ,という感じです.

(2011/09/23 18:58), SASADA Koichi wrote:

ファイナライザの実行は,何時起こるかわからないものなので,デッドロック
の可能性がある処理を行うのは,プログラムが悪い,ということになります.基
本的には,デッドロックを起こさないように書き直す必要がありますが,例えば
上記の場合では,mutex.trylock を利用することで回避することができます.

すみません,trylock ではダメですね.

うーん,これはどうするべきかな.ファイナライズ処理を遅延させるように
コードを書き換えれば解決できますが,ちょっと大がかりな気もしますね.問題
が weakref だけなら,大がかりでもいい気がしますが.

この問題は,pthread_mutex* で管理している状況をシグナルハンドラでどう
処理するか,みたいなのに似ていると思うのですが,そもそも pthread_mutex*
はシグナルセーフじゃないから使えないんだよな.

(2011/09/23 19:02), SASADA Koichi wrote:

うーん,これはどうするべきかな.ファイナライズ処理を遅延させるように
コードを書き換えれば解決できますが,ちょっと大がかりな気もしますね.問題
が weakref だけなら,大がかりでもいい気がしますが.

わかりづらい文章になってしまってすみません.weakref 側を,ファイナライ
ザ処理を遅延できるように大がかりに書き換えればよい,という意図でした.例
えば,ファイナライザはこの処理をファイナライザの 後で 実行するように,
例えば Thread 作っちゃうとかすれば解決できます.

weakref のコードを見ていないので,どのように解決するのがスマートかわか
りませんが,現状ですと「単に weakref のバグです」としか言えないんじゃな
いかと思います.ただ,Ruby 自体に「こういう機能があるともっと綺麗に書け
る」といった話に発展する可能性は否定しません.

なかだです。

At Sat, 24 Sep 2011 11:38:54 +0900,
SASADA Koichi wrote in [ruby-dev:44538]:

(2011/09/23 19:02), SASADA Koichi wrote:

うーん,これはどうするべきかな.ファイナライズ処理を遅延させるように
コードを書き換えれば解決できますが,ちょっと大がかりな気もしますね.問題
が weakref だけなら,大がかりでもいい気がしますが.

わかりづらい文章になってしまってすみません.weakref 側を,ファイナライ
ザ処理を遅延できるように大がかりに書き換えればよい,という意図でした.例
えば,ファイナライザはこの処理をファイナライザの 後で 実行するように,
例えば Thread 作っちゃうとかすれば解決できます.

weakrefのマップからの削除処理は、ファイナライザから遅延させてはまずいで
す。削除が完了する前にファイナライザが終了してしまうと、対象のオブジェ
クトは再利用される可能性があり、その時点でweakrefから参照すると意図しな
いオブジェクトが得られることになります。

第一の問題点は、weakrefのファイナライズ処理が再入不能なのに、ファイナラ
イザ自体は再入することがあり得ることです。[ruby-dev:44527]にある再現コー
ドのように、weakrefのファイナライズ処理で内部的に使っているMutexが外部
からも容易にアクセスできてしまうことも問題といっていいでしょう。

とりあえずファイナライザで再入しないようにするパッチです。

diff --git i/gc.c w/gc.c
index f9a945c…fad49e0 100644
— i/gc.c
+++ w/gc.c
@@ -345,6 +345,7 @@ typedef struct rb_objspace {
int dont_gc;
int dont_lazy_sweep;
int during_gc;

  • rb_atomic_t finalizing;
    } flags;
    struct {
    st_table *table;
    @@ -387,6 +388,7 @@ int *ruby_initial_gc_stress_ptr =
    &rb_objspace.gc_stress;
    #define heaps_freed objspace->heap.freed
    #define dont_gc objspace->flags.dont_gc
    #define during_gc objspace->flags.during_gc
    +#define finalizing objspace->flags.finalizing
    #define finalizer_table objspace->final.table
    #define deferred_final_list objspace->final.deferred
    #define mark_stack objspace->markstack.buffer
    @@ -2064,7 +2066,7 @@ slot_sweep(rb_objspace_t *objspace, struct
    heaps_slot *sweep_slot)
    }
    objspace->heap.final_num += final_num;
  • if (deferred_final_list) {
  • if (deferred_final_list && !finalizing) {
    rb_thread_t *th = GET_THREAD();
    if (th) {
    RUBY_VM_SET_FINALIZER_INTERRUPT(th);
    @@ -2968,7 +2970,10 @@ finalize_deferred(rb_objspace_t *objspace)
    void
    rb_gc_finalize_deferred(void)
    {
  • finalize_deferred(&rb_objspace);
  • rb_objspace_t *objspace = &rb_objspace;
  • if (ATOMIC_SET(finalizing, 1)) return;
  • finalize_deferred(objspace);
  • ATOMIC_SET(finalizing, 0);
    }

static int
@@ -3020,6 +3025,8 @@ rb_objspace_call_finalizer(rb_objspace_t
objspace)
/
run finalizers */
gc_clear_mark_on_sweep_slots(objspace);

  • if (ATOMIC_SET(finalizing, 1)) return;

  • do {
    /* XXX: this loop will make no sense /
    /
    because mark will not be removed */
    @@ -3082,6 +3089,7 @@ rb_objspace_call_finalizer(rb_objspace_t
    *objspace)

    st_free_table(finalizer_table);
    finalizer_table = 0;

  • ATOMIC_SET(finalizing, 0);
    }

void
@@ -3089,7 +3097,7 @@ rb_gc(void)
{
rb_objspace_t *objspace = &rb_objspace;
garbage_collect(objspace);

  • finalize_deferred(objspace);
  • if (!finalizing) finalize_deferred(objspace);
    free_unused_heaps(objspace);
    }

Issue #5350 has been updated by Shota F…

ささださんがパッチを書いてくれました.
(許可を得て)MLに転載しておきます.

手元では再現しなくなりましたが, ([ruby-dev:44525] の再現コードを使用)
どうでしょうか.

diff --git a/lib/weakref.rb b/lib/weakref.rb
index ee5444a…f3e669b 100644
— a/lib/weakref.rb
+++ b/lib/weakref.rb
@@ -28,7 +28,7 @@ class WeakRef < Delegator
@@id_rev_map = {} # ref → obj
@@mutex = Mutex.new
@@final = lambda {|id|

  • @@mutex.synchronize {
  • pr = lambda{
    rids = @@id_map[id]
    if rids
    for rid in rids
    @@ -43,6 +43,19 @@ class WeakRef < Delegator
    @@id_map.delete(rid) if @@id_map[rid].empty?
    end
    }
  • if @@mutex.try_lock
  •  begin
    
  •    pr.call
    
  •  ensure
    
  •    @@mutex.unlock
    
  •  end
    
  • else
  •  Thread.new{
    
  •    @@mutex.synchronize{
    
  •      pr.call
    
  •    }
    
  •  }
    
  • end
    }


Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Open
Priority: Low
Assignee:
Category:
Target version: 1.9.x
ruby -v: -

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by Koichi Sasada.

Status changed from Open to Assigned
Assignee set to Nobuyoshi N.


Bug #5350: WeakRef で謎の NoMethodError

Author: Makoto K.
Status: Assigned
Priority: Normal
Assignee: Nobuyoshi N.
Category:
Target version: 2.0.0
ruby -v: -

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by zzak (Zachary S.).

Could someone help me understand WeakMap?

I’m looking for a good example, or use-case for it to use in
documentation.

Thank you!

Bug #5350: WeakRef で謎の NoMethodError

Author: metanest (Makoto K.)
Status: Closed
Priority: Normal
Assignee: nobu (Nobuyoshi N.)
Category:
Target version: 2.0.0
ruby -v: -

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by naruse (Yui NARUSE).

Status changed from Closed to Assigned


Bug #5350: WeakRef で謎の NoMethodError

Author: metanest (Makoto K.)
Status: Assigned
Priority: Normal
Assignee: nobu (Nobuyoshi N.)
Category:
Target version: 2.0.0
ruby -v: -

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

Issue #5350 has been updated by nobu (Nobuyoshi N.).

Status changed from Assigned to Closed

Please file new ticket for documentation.

Bug #5350: WeakRef で謎の NoMethodError

Author: metanest (Makoto K.)
Status: Closed
Priority: Normal
Assignee: nobu (Nobuyoshi N.)
Category:
Target version: 2.0.0
ruby -v: -

添付のようなスクリプトを r18232 以降の ruby 1.9 で走らせると、以下のように
RefError ではなく NoMethodError が上がってくる、ということが起きます。
( value メソッドを呼ぶ直前に weakref_alive? を呼んでみると true が
返っています )

r18220 以前では正常に動きます( r18221 ~ r18231 では core を吐きます)。

ruby 1.9.0 (2008-07-27 revision 0) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
[17188951200]:WeakRef (NoMethodError)
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:29:in block in part' from ../weakref_bug.rb:27:in downto’
from …/weakref_bug.rb:27:in each' from ../weakref_bug.rb:27:in part’
from …/weakref_bug.rb:38:in block in <main>' from ../weakref_bug.rb:36:in each’
from …/weakref_bug.rb:36:in `’

ruby 1.9.4dev (2011-07-18 trunk 32577) [x86_64-freebsd8.2]
…/weakref_bug.rb:20:in part': undefined method value’ for
"…/weakref_bug.rb:36:in <main>'":WeakRef (NoMethodError) from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:29:in block in part’
from …/weakref_bug.rb:27:in downto' from ../weakref_bug.rb:27:in each’
from …/weakref_bug.rb:27:in part' from ../weakref_bug.rb:38:in block in ’
from …/weakref_bug.rb:36:in each' from ../weakref_bug.rb:36:in

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] gc_sweep(): unknown data type 0x0(0x801019088)
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
c:0022 p:0069 s:0068 b:0068 l:000067 d:000067 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58
c:0021 p:0007 s:0065 b:0065 l:000064 d:000064 METHOD
/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139
c:0020 p:---- s:0058 b:0058 l:000057 d:000057 FINISH :eql?
c:0019 p:0041 s:0056 b:0055 l:000054 d:000054 METHOD
…/weakref_bug.rb:20
c:0018 p:0032 s:0048 b:0047 l:000036 d:000046 BLOCK
…/weakref_bug.rb:29
c:0017 p:---- s:0046 b:0046 l:000045 d:000045 FINISH :==
c:0016 p:---- s:0044 b:0044 l:000039 d:000043 IFUNC :==
c:0015 p:---- s:0042 b:0042 l:000041 d:000041 CFUNC :downto
c:0014 p:---- s:0040 b:0040 l:000039 d:000039 CFUNC :each
c:0013 p:0074 s:0037 b:0037 l:000036 d:000036 METHOD
…/weakref_bug.rb:27
c:0012 p:0032 s:0030 b:0029 l:000018 d:000028 BLOCK
…/weakref_bug.rb:29
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :==
c:0010 p:---- s:0026 b:0026 l:000021 d:000025 IFUNC :==
c:0009 p:---- s:0024 b:0024 l:000023 d:000023 CFUNC :downto
c:0008 p:---- s:0022 b:0022 l:000021 d:000021 CFUNC :each
c:0007 p:0074 s:0019 b:0019 l:000018 d:000018 METHOD
…/weakref_bug.rb:27
c:0006 p:0013 s:0012 b:0012 l:000005 d:000011 BLOCK
…/weakref_bug.rb:38
c:0005 p:---- s:0011 b:0011 l:000010 d:000010 FINISH :method_added
c:0004 p:---- s:0009 b:0009 l:000008 d:000008 CFUNC :each
c:0003 p:0047 s:0006 b:0006 l:000005 d:000005 TOP
…/weakref_bug.rb:36
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH
:private_class_method
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:
[BUG] object allocation during garbage collection phase
ruby 1.9.0 (2008-07-25 revision 0) [x86_64-freebsd8.2]

– control frame ----------
c:0023 p:---- s:0072 b:0072 l:000071 d:000071 CFUNC :_id2ref
(上と同じなので省略)
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP

DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in
_id2ref'" DBG> : "/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/weakref.rb:58:in getobj’”
DBG> :
“/home/ksmakoto/ruby-working/ruby-weakref/lib/ruby/1.9.0/delegate.rb:139:in
method_missing'" DBG> : "../weakref_bug.rb:20:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:29:in block in part'" DBG> : "../weakref_bug.rb:27:in downto’”
DBG> : “…/weakref_bug.rb:27:in each'" DBG> : "../weakref_bug.rb:27:in part’”
DBG> : “…/weakref_bug.rb:38:in block in <main>'" DBG> : "../weakref_bug.rb:36:in each’”
DBG> : “…/weakref_bug.rb:36:in `'”
Abort trap: 6 (core dumped)

$B$J$+$@$G$9!#(B

Thu, 29 Sep 2011 20:48:38 +0900,
Nobuyoshi N. wrote in [ruby-dev:44562]:

$BBh0l$NLdBjE@$O!"(Bweakref$B$N%U%!%$%J%i%$%:=hM}$,:FF~ITG=$J$N$K!"%U%!%$%J%i(B
$B%$%6<+BN$O:FF~$9$k$3$H$,$"$jF@$k$3$H$G$9!#(B[ruby-dev:44527]$B$K$"$k:F8=%3!<(B

$B%I$N$h$&$K!"(Bweakref$B$N%U%!%$%J%i%$%:=hM}$GFbItE*$K;H$C$F$$$k(BMutex$B$,30It(B

$B$+$i$bMF0W$K%"%/%;%9$G$-$F$7$^$&$3$H$bLdBj$H$$$C$F$$$$$G$7$g$&!#(B

ObjectSpace::WeakMap$B$rDI2C$7$F$=$l$r;H$&$h$&$K$7$?%Q%C%A$G$9!#(B

diff --git i/gc.c w/gc.c
index fad49e0…ba0cac4 100644
— i/gc.c
+++ w/gc.c
@@ -402,6 +402,9 @@ int *ruby_initial_gc_stress_ptr =
&rb_objspace.gc_stress;
#define nonspecial_obj_id(obj) (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG)

static void rb_objspace_call_finalizer(rb_objspace_t *objspace);
+static VALUE define_final0(VALUE obj, VALUE block);
+VALUE rb_define_final(VALUE obj, VALUE block);
+VALUE rb_undefine_final(VALUE obj);

#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
rb_objspace_t *
@@ -2829,6 +2832,12 @@ os_each_obj(int argc, VALUE *argv, VALUE os)
static VALUE
undefine_final(VALUE os, VALUE obj)
{

  • return rb_undefine_final(obj);
    +}

+VALUE
+rb_undefine_final(VALUE obj)
+{
rb_objspace_t *objspace = &rb_objspace;
st_data_t data = obj;
rb_check_frozen(obj);
@@ -2849,9 +2858,7 @@ undefine_final(VALUE os, VALUE obj)
static VALUE
define_final(int argc, VALUE *argv, VALUE os)
{

  • rb_objspace_t *objspace = &rb_objspace;
  • VALUE obj, block, table;
  • st_data_t data;
  • VALUE obj, block;

    rb_scan_args(argc, argv, “11”, &obj, &block);
    rb_check_frozen(obj);
    @@ -2862,6 +2869,16 @@ define_final(int argc, VALUE *argv, VALUE os)
    rb_raise(rb_eArgError, “wrong type argument %s (should be callable)”,
    rb_obj_classname(block));
    }

  • return define_final0(obj, block);
    +}

+static VALUE
+define_final0(VALUE obj, VALUE block)
+{

  • rb_objspace_t *objspace = &rb_objspace;
  • VALUE table;
  • st_data_t data;
  • if (!FL_ABLE(obj)) {
    rb_raise(rb_eArgError, “cannot define finalizer for %s”,
    rb_obj_classname(obj));
    @@ -2883,6 +2900,17 @@ define_final(int argc, VALUE *argv, VALUE os)
    return block;
    }

+VALUE
+rb_define_final(VALUE obj, VALUE block)
+{

  • rb_check_frozen(obj);
  • if (!rb_respond_to(block, rb_intern(“call”))) {
  • rb_raise(rb_eArgError, “wrong type argument %s (should be callable)”,
  • rb_obj_classname(block));
    
  • }
  • return define_final0(obj, block);
    +}

void
rb_gc_copy_finalizer(VALUE dest, VALUE obj)
{
@@ -3656,6 +3684,157 @@ gc_profile_total_time(VALUE self)

  • See also GC.count, GC.malloc_allocated_size and
    GC.malloc_allocations
    */

+struct weakmap {

  • st_table obj2wmap; / obj -> [ref,…] */
  • st_table wmap2obj; / ref -> obj */
  • VALUE final;
    +};

+static int
+wmap_mark_map(st_data_t key, st_data_t val, st_data_t arg)
+{

  • FL_SET((VALUE)val, FL_MARK);
  • return ST_CONTINUE;
    +}

+static void
+wmap_mark(void *ptr)
+{

  • struct weakmap *w = ptr;
  • st_foreach(w->obj2wmap, wmap_mark_map, 0);
  • rb_gc_mark(w->final);
    +}

+static int
+wmap_free_map(st_data_t key, st_data_t val, st_data_t arg)
+{

  • rb_ary_resize((VALUE)val, 0);
  • return ST_CONTINUE;
    +}

+static void
+wmap_free(void *ptr)
+{

  • struct weakmap *w = ptr;
  • st_foreach(w->obj2wmap, wmap_free_map, 0);
  • st_clear(w->obj2wmap);
  • st_clear(w->wmap2obj);
    +}

+size_t rb_ary_memsize(VALUE ary);
+static int
+wmap_memsize_map(st_data_t key, st_data_t val, st_data_t arg)
+{

  • *(size_t *)arg += rb_ary_memsize((VALUE)val);
  • return ST_CONTINUE;
    +}

+static size_t
+wmap_memsize(const void *ptr)
+{

  • size_t size;
  • const struct weakmap *w = ptr;
  • if (!w) return 0;
  • size = sizeof(*w);
  • size += st_memsize(w->obj2wmap);
  • size += st_memsize(w->wmap2obj);
  • st_foreach(w->obj2wmap, wmap_memsize_map, (st_data_t)&size);
  • return size;
    +}

+static const rb_data_type_t weakmap_type = {

  • “weakmap”,
  • {
  • wmap_mark,
  • wmap_free,
  • wmap_memsize,
  • }
    +};

+static VALUE
+wmap_allocate(VALUE klass)
+{

  • struct weakmap *w;
  • VALUE obj = TypedData_Make_Struct(klass, struct weakmap,
    &weakmap_type, w);
  • w->obj2wmap = st_init_numtable();
  • w->wmap2obj = st_init_numtable();
  • w->final = rb_obj_method(obj, ID2SYM(rb_intern(“finalize”)));
  • return obj;
    +}

+static VALUE
+wmap_finalize(VALUE self, VALUE obj)
+{

  • st_data_t data;
  • VALUE rids;
  • long i;
  • struct weakmap *w;
  • TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
  • obj = NUM2PTR(obj);
  • data = (st_data_t)obj;
  • if (st_delete(w->obj2wmap, &data, &data)) {
  • rids = (VALUE)data;
  • for (i = 0; i < RARRAY_LEN(rids); ++i) {
  •  data = (st_data_t)RARRAY_PTR(rids)[i];
    
  •  st_delete(w->wmap2obj, &data, NULL);
    
  • }
  • }
  • data = (st_data_t)obj;
  • if (st_delete(w->wmap2obj, &data, &data)) {
  • VALUE rid = (VALUE)data;
  • int empty = 1;
  • if (st_lookup(w->obj2wmap, (st_data_t)rid, &data)) {
  •  rb_ary_delete((VALUE)data, obj);
    
  •  empty = !RARRAY_LEN((VALUE)data);
    
  • }
  • if (empty) {
  •  data = (st_data_t)rid;
    
  •  st_delete(w->obj2wmap, &data, &data);
    
  • }
  • }
    +}

+static VALUE
+wmap_aset(VALUE self, VALUE wmap, VALUE orig)
+{

  • st_data_t data;
  • VALUE rids;
  • struct weakmap *w;
  • TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
  • rb_define_final(orig, w->final);
  • rb_define_final(wmap, w->final);
  • if (!st_lookup(w->obj2wmap, (st_data_t)orig, &data)) {
  • rids = rb_ary_tmp_new(1);
  • st_insert(w->obj2wmap, (st_data_t)orig, (st_data_t)rids);
  • }
  • else {
  • rids = (VALUE)data;
  • }
  • rb_ary_push(rids, orig);
  • st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
  • return nonspecial_obj_id(orig);
    +}

+static VALUE
+wmap_aref(VALUE self, VALUE wmap)
+{

  • st_data_t data;
  • VALUE obj;
  • struct weakmap *w;
  • rb_objspace_t *objspace = &rb_objspace;
  • TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
  • if (!st_lookup(w->wmap2obj, (st_data_t)wmap, &data)) return Qnil;
  • obj = (VALUE)data;
  • if (!is_id_value(objspace, obj)) return Qnil;
  • if (!is_live_object(objspace, obj)) return Qnil;
  • return obj;
    +}

/*

  • The GC module provides an interface to Ruby’s mark and

  • sweep garbage collection mechanism. Some of the underlying methods
    @@ -3710,6 +3889,14 @@ Init_GC(void)

    rb_define_module_function(rb_mObSpace, “count_objects”,
    count_objects, -1);

  • {
  • VALUE rb_cWeakMap = rb_define_class_under(rb_mObSpace, “WeakMap”,
    rb_cObject);
  • rb_define_alloc_func(rb_cWeakMap, wmap_allocate);
  • rb_define_method(rb_cWeakMap, “[]=”, wmap_aset, 2);
  • rb_define_method(rb_cWeakMap, “[]”, wmap_aref, 1);
  • rb_define_private_method(rb_cWeakMap, “finalize”, wmap_finalize, 1);
  • }

#if CALC_EXACT_MALLOC_SIZE
rb_define_singleton_method(rb_mGC, “malloc_allocated_size”,
gc_malloc_allocated_size, 0);
rb_define_singleton_method(rb_mGC, “malloc_allocations”,
gc_malloc_allocations, 0);
diff --git i/lib/weakref.rb w/lib/weakref.rb
index ee5444a…1fea9a9 100644
— i/lib/weakref.rb
+++ w/lib/weakref.rb
@@ -1,5 +1,4 @@
require “delegate”
-require ‘thread’

Weak Reference class that allows a referenced object to be

garbage-collected. A WeakRef may be used exactly like the object it

@@ -16,6 +15,7 @@ require ‘thread’

p foo.to_s # should raise exception (recycled)

class WeakRef < Delegator

  • @@__map = ::ObjectSpace::WeakMap.new

    RefError is raised when a referenced object has been recycled by

the
@@ -24,51 +24,17 @@ class WeakRef < Delegator
class RefError < StandardError
end

  • @@id_map = {} # obj -> [ref,…]

  • @@id_rev_map = {} # ref -> obj

  • @@mutex = Mutex.new

  • @@final = lambda {|id|

  • @@mutex.synchronize {

  •  rids = @@id_map[id]
    
  •  if rids
    
  •    for rid in rids
    
  •      @@id_rev_map.delete(rid)
    
  •    end
    
  •    @@id_map.delete(id)
    
  •  end
    
  •  rid = @@id_rev_map[id]
    
  •  if rid
    
  •    @@id_rev_map.delete(id)
    
  •    @@id_map[rid].delete(id)
    
  •    @@id_map.delete(rid) if @@id_map[rid].empty?
    
  •  end
    
  • }

  • }

  • Creates a weak reference to +orig+

    def initialize(orig)

  • @__id = orig.object_id

  • ObjectSpace.define_finalizer orig, @@final

  • ObjectSpace.define_finalizer self, @@final

  • @@mutex.synchronize {

  •  @@id_map[@__id] = [] unless @@id_map[@__id]
    
  • }

  • @@id_map[@__id].push self.object_id

  • @@id_rev_map[self.object_id] = @__id

  • @@__map[self] = orig
    super
    end

def getobj # :nodoc:

  • unless @@id_rev_map[self.object_id] == @__id
  •  Kernel::raise RefError, "Invalid Reference - probably recycled", 
    

Kernel::caller(2)

  • end
  • begin
  •  ObjectSpace._id2ref(@__id)
    
  • rescue RangeError
  • @@__map[self] or
    Kernel::raise RefError, “Invalid Reference - probably recycled”,
    Kernel::caller(2)
  • end
    end

def setobj(obj) # :nodoc:
@@ -78,7 +44,7 @@ class WeakRef < Delegator

Returns true if the referenced object is still alive.

def weakref_alive?

  • @@id_rev_map[self.object_id] == @__id
  • !!@@__map[self]
    end
    end