* 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38080 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
kosaki 2012-11-30 17:39:36 +00:00
parent a1d837ccc1
commit 6ca32179e6
2 changed files with 37 additions and 24 deletions

View File

@ -1,3 +1,10 @@
Sat Dec 1 01:19:34 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* 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@mbf.nifty.com> Sat Dec 1 02:04:23 2012 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
* test/ruby/envutil.rb (Test::Unit::Assertions#assert_in_out_err): * test/ruby/envutil.rb (Test::Unit::Assertions#assert_in_out_err):

View File

@ -63,15 +63,18 @@ class ConditionVariable
# even if no other thread doesn't signal. # even if no other thread doesn't signal.
# #
def wait(mutex, timeout=nil) def wait(mutex, timeout=nil)
begin Thread.async_interrupt_timing(StandardError => :defer) do
# TODO: mutex should not be used begin
@waiters_mutex.synchronize do Thread.async_interrupt_timing(StandardError => :on_blocking) do
@waiters.push(Thread.current) @waiters_mutex.synchronize do
end @waiters.push(Thread.current)
mutex.sleep timeout end
ensure mutex.sleep timeout
@waiters_mutex.synchronize do end
@waiters.delete(Thread.current) ensure
@waiters_mutex.synchronize do
@waiters.delete(Thread.current)
end
end end
end end
self self
@ -81,11 +84,13 @@ class ConditionVariable
# Wakes up the first thread in line waiting for this lock. # Wakes up the first thread in line waiting for this lock.
# #
def signal def signal
begin Thread.async_interrupt_timing(RuntimeError => :on_blocking) do
t = @waiters_mutex.synchronize {@waiters.shift} begin
t.run if t t = @waiters_mutex.synchronize {@waiters.shift}
rescue ThreadError t.run if t
retry rescue ThreadError
retry # t was alread dead?
end
end end
self self
end end
@ -94,16 +99,17 @@ class ConditionVariable
# Wakes up all threads waiting for this lock. # Wakes up all threads waiting for this lock.
# #
def broadcast def broadcast
# TODO: incomplete Thread.async_interrupt_timing(RuntimeError => :on_blocking) do
waiters0 = nil waiters0 = nil
@waiters_mutex.synchronize do @waiters_mutex.synchronize do
waiters0 = @waiters.dup waiters0 = @waiters.dup
@waiters.clear @waiters.clear
end end
for t in waiters0 for t in waiters0
begin begin
t.run t.run
rescue ThreadError rescue ThreadError
end
end end
end end
self self