From: Nobuyoshi Nakada Date: 2007-04-19T13:20:15+09:00 Subject: Re: Why does this code deadlock? Hi, At Wed, 18 Apr 2007 16:53:25 +0900, Yukihiro Matsumoto wrote in [ruby-talk:248325]: > |At Wed, 18 Apr 2007 08:34:03 +0900, > |Bill Kelly wrote in [ruby-talk:248300]: > |> require 'net/ftp' > |> Thread.abort_on_exception = true > |> ftp = Net::FTP.new('ftp.idsoftware.com') > | th = Thread.new {$SAFE=4; ftp.login('anonymous', 'abc@def.com')} > | Thread.critical = false > | p th.value > > Who set Thread.critical? It should be fixed, I think. mon_acquire called from mon_enter fails because of SecurityError, and leaves Thread.critical true. Index: lib/monitor.rb =================================================================== --- lib/monitor.rb (revision 12191) +++ lib/monitor.rb (working copy) @@ -106,12 +106,15 @@ def wait(timeout = nil) ensure Thread.critical = true - if timer && timer.alive? - Thread.kill(timer) + begin + if timer && timer.alive? + Thread.kill(timer) + end + if @waiters.include?(Thread.current) # interrupted? + @waiters.delete(Thread.current) + end + @monitor.instance_eval {mon_enter_for_cond(count)} + ensure + Thread.critical = false end - if @waiters.include?(Thread.current) # interrupted? - @waiters.delete(Thread.current) - end - @monitor.instance_eval {mon_enter_for_cond(count)} - Thread.critical = false end end @@ -211,4 +214,5 @@ def mon_enter mon_acquire(@mon_entering_queue) @mon_count += 1 + ensure Thread.critical = false end @@ -300,6 +304,7 @@ def mon_exit_for_cond count = @mon_count @mon_count = 0 - mon_release return count + ensure + mon_release end end -- Nobu Nakada