杉浦です。
またも細かい話で恐縮ですが……
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