From: SASADA Koichi Date: 2011-09-24T10:58:41+09:00 Subject: [ruby-dev:44536] Re: [ruby-dev:44535] Re: [ruby-dev:44534] Re: [ruby-dev:44532] [Ruby 1.9 - Bug #5350] WeakRef で謎の NoMethodError  ささだです. (2011/09/23 18:47), Shota Fukumori (sora_h) wrote: > 元の問題がややこしくなっているので一旦まとめると, > > 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. その他何らかの良い方法  問題のまとめをありがとうございます.  ファイナライザの実行は,何時起こるかわからないものなので,デッドロック の可能性がある処理を行うのは,プログラムが悪い,ということになります.基 本的には,デッドロックを起こさないように書き直す必要がありますが,例えば 上記の場合では,mutex.trylock を利用することで回避することができます. # 本質的に,何かしら他の対処が必要な話だろうか? -- // SASADA Koichi at atdot dot net