From 69743fbd85b659601174bff9fb61abc8c662c13b Mon Sep 17 00:00:00 2001 From: nahi Date: Tue, 20 Oct 2009 16:14:25 +0000 Subject: [PATCH] * lib/monitor.rb (MonitorMixin.mon_release): ensure the scheduled thread to be alive when a thread is releasing a monitor. #2240 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@25420 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ lib/monitor.rb | 10 +++++++--- test/monitor/test_monitor.rb | 29 +++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ef14f5b2e..f472a11522 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed Oct 21 01:19:56 2009 NAKAMURA, Hiroshi + + * lib/monitor.rb (MonitorMixin.mon_release): ensure the scheduled + thread to be alive when a thread is releasing a monitor. #2240 + Wed Oct 21 00:28:52 2009 NAKAMURA, Hiroshi * lib/webrick/httpauth/digestauth.rb: typo in exception message fixed. diff --git a/lib/monitor.rb b/lib/monitor.rb index 4c146c8086..9158f9fb32 100644 --- a/lib/monitor.rb +++ b/lib/monitor.rb @@ -288,11 +288,15 @@ module MonitorMixin @mon_owner = Thread.current end + # mon_release requires Thread.critical == true def mon_release @mon_owner = nil - t = @mon_waiting_queue.shift - t = @mon_entering_queue.shift unless t - t.wakeup if t + while t = @mon_waiting_queue.shift || @mon_entering_queue.shift + if t.alive? + t.wakeup + return + end + end end def mon_enter_for_cond(count) diff --git a/test/monitor/test_monitor.rb b/test/monitor/test_monitor.rb index b539cb3cca..7593d3f938 100644 --- a/test/monitor/test_monitor.rb +++ b/test/monitor/test_monitor.rb @@ -54,6 +54,32 @@ class TestMonitor < Test::Unit::TestCase assert_equal((1..10).to_a, ary) end + def test_killed_thread_in_synchronize + ary = [] + queue = Queue.new + t1 = Thread.start { + queue.pop + @monitor.synchronize { + ary << :t1 + } + } + t2 = Thread.start { + queue.pop + @monitor.synchronize { + ary << :t2 + } + } + @monitor.synchronize do + queue.enq(nil) + queue.enq(nil) + assert_equal([], ary) + t1.kill + t2.kill + ary << :main + end + assert_equal([:main], ary) + end + def test_try_enter queue1 = Queue.new queue2 = Queue.new @@ -94,7 +120,10 @@ class TestMonitor < Test::Unit::TestCase assert_equal(true, result1) assert_equal("bar", a) end + end + def test_timedwait + cond = @monitor.new_cond b = "foo" queue2 = Queue.new Thread.start do