From: Shota Fukumori Date: 2011-09-23T22:45:57+09:00 Subject: [ruby-dev:44525] [Ruby 1.9 - Bug #5350] WeakRef で謎の NoMethodError Issue #5350 has been updated by Shota Fukumori. 調査結果を報告します. 再現コードさらに短縮-- 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 , 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 http://redmine.ruby-lang.org/issues/5350 Author: Makoto Kishimoto 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
' 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 `
'":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
'" DBG> : "../weakref_bug.rb:36:in `each'" DBG> : "../weakref_bug.rb:36:in `
'" Abort trap: 6 (core dumped) -- http://redmine.ruby-lang.org