ruby-changes:26023
From: kosaki <ko1@a...>
Date: Sat, 1 Dec 2012 02:41:58 +0900 (JST)
Subject: [ruby-changes:26023] kosaki:r38080 (trunk): * lib/thread.rb (ConditionVariable#broadcast): protect from
kosaki 2012-12-01 02:39:36 +0900 (Sat, 01 Dec 2012) New Revision: 38080 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38080 Log: * lib/thread.rb (ConditionVariable#broadcast): protect from async interrupt by using Thread.async_interrupt_timing. * lib/thread.rb (ConditionVariable#signal): ditto. * lib/thread.rb (ConditionVariable#wait): ditto. Modified files: trunk/ChangeLog trunk/lib/thread.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 38079) +++ ChangeLog (revision 38080) @@ -1,3 +1,10 @@ +Sat Dec 1 01:19:34 2012 KOSAKI Motohiro <kosaki.motohiro@g...> + + * lib/thread.rb (ConditionVariable#broadcast): protect from + async interrupt by using Thread.async_interrupt_timing. + * lib/thread.rb (ConditionVariable#signal): ditto. + * lib/thread.rb (ConditionVariable#wait): ditto. + Sat Dec 1 02:04:23 2012 Kazuhiro NISHIYAMA <zn@m...> * test/ruby/envutil.rb (Test::Unit::Assertions#assert_in_out_err): Index: lib/thread.rb =================================================================== --- lib/thread.rb (revision 38079) +++ lib/thread.rb (revision 38080) @@ -63,16 +63,19 @@ # even if no other thread doesn't signal. # def wait(mutex, timeout=nil) - begin - # TODO: mutex should not be used - @waiters_mutex.synchronize do - @waiters.push(Thread.current) + Thread.async_interrupt_timing(StandardError => :defer) do + begin + Thread.async_interrupt_timing(StandardError => :on_blocking) do + @waiters_mutex.synchronize do + @waiters.push(Thread.current) + end + mutex.sleep timeout + end + ensure + @waiters_mutex.synchronize do + @waiters.delete(Thread.current) + end end - mutex.sleep timeout - ensure - @waiters_mutex.synchronize do - @waiters.delete(Thread.current) - end end self end @@ -81,11 +84,13 @@ # Wakes up the first thread in line waiting for this lock. # def signal - begin - t = @waiters_mutex.synchronize {@waiters.shift} - t.run if t - rescue ThreadError - retry + Thread.async_interrupt_timing(RuntimeError => :on_blocking) do + begin + t = @waiters_mutex.synchronize {@waiters.shift} + t.run if t + rescue ThreadError + retry # t was alread dead? + end end self end @@ -94,17 +99,18 @@ # Wakes up all threads waiting for this lock. # def broadcast - # TODO: incomplete - waiters0 = nil - @waiters_mutex.synchronize do - waiters0 = @waiters.dup - @waiters.clear - end - for t in waiters0 - begin - t.run - rescue ThreadError + Thread.async_interrupt_timing(RuntimeError => :on_blocking) do + waiters0 = nil + @waiters_mutex.synchronize do + waiters0 = @waiters.dup + @waiters.clear end + for t in waiters0 + begin + t.run + rescue ThreadError + end + end end self end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/