From: Tatsuki Sugiura Date: 2004-06-26T03:57:34+09:00 Subject: [ruby-dev:23802] 同一スレッドで Mutex の2重ロック 杉浦です。 またも細かい話で恐縮ですが…… Mutex#synchronize を同じスレッドからネストして呼び出すと (当たり前ですが)デッドロックしてしまいます。 $ ruby -r thread -e ' m = Mutex.new Thread.start{ m.synchronize{ m.synchronize{ } } }.join ' deadlock 0x402abe64: sleep:- - /usr/lib/ruby/1.8/thread.rb:96 deadlock 0x402bf7c0: sleep:J(0x402abe64) (main) - -e:10 -e:10:in `join': Thread(0x402bf7c0): deadlock (fatal) from -e:10 他にスレッドがある場合は、join を呼んだときに deadlock と言われるので まだ良いのですが、メインスレッドしかない場合は /usr/lib/ruby/1.8/thread.rb:96:in `stop': stopping only thread (ThreadError) と言う例外があがってしまい、何のことだか分かりません。 と言うわけで、@locked フラグにロック元のスレッドを保持しておいて、 デッドロック状態になったら即座に例外をあげるパッチを書いてみました。 取り込んで貰うことは出来ますでしょうか? -- Tatsuki Sugiura mailto:sugi@nemui.org --- lib/thread.rb.orig 2004-06-24 02:58:29.000000000 +0900 +++ lib/thread.rb 2004-06-26 03:49:55.000000000 +0900 @@ -69,7 +69,7 @@ # Returns +true+ if this lock is currently held by some thread. # def locked? - @locked + @locked && true end # @@ -80,7 +80,7 @@ result = false Thread.critical = true unless @locked - @locked = true + @locked = Thread.current result = true end Thread.critical = false @@ -92,10 +92,12 @@ # def lock while (Thread.critical = true; @locked) + @locked == Thread.current and + raise ThreadError, "deadlock; locked by same thread twice." @waiting.push Thread.current Thread.stop end - @locked = true + @locked = Thread.current Thread.critical = false self end