1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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>
* 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.
#
def wait(mutex, timeout=nil)
begin
# TODO: mutex should not be used
@waiters_mutex.synchronize do
@waiters.push(Thread.current)
end
mutex.sleep timeout
ensure
@waiters_mutex.synchronize do
@waiters.delete(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
end
self
@ -81,11 +84,13 @@ class ConditionVariable
# 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,16 +99,17 @@ class ConditionVariable
# 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