mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
lib/monitor.rb: avoid race conditions by Thread.handle_interrupt
Suggested by Benoit Daloze. [ruby-core:88502] [Bug #14998] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66061 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
db7338fd75
commit
6ec1720aa3
2 changed files with 33 additions and 7 deletions
|
@ -103,13 +103,17 @@ module MonitorMixin
|
|||
# even if no other thread doesn't signal.
|
||||
#
|
||||
def wait(timeout = nil)
|
||||
@monitor.__send__(:mon_check_owner)
|
||||
count = @monitor.__send__(:mon_exit_for_cond)
|
||||
begin
|
||||
@cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
|
||||
return true
|
||||
ensure
|
||||
@monitor.__send__(:mon_enter_for_cond, count)
|
||||
Thread.handle_interrupt(Exception => :never) do
|
||||
@monitor.__send__(:mon_check_owner)
|
||||
count = @monitor.__send__(:mon_exit_for_cond)
|
||||
begin
|
||||
Thread.handle_interrupt(Exception => :immediate) do
|
||||
@cond.wait(@monitor.instance_variable_get(:@mon_mutex), timeout)
|
||||
end
|
||||
return true
|
||||
ensure
|
||||
@monitor.__send__(:mon_enter_for_cond, count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -269,4 +269,26 @@ class TestMonitor < Test::Unit::TestCase
|
|||
# end
|
||||
# cumber_thread.kill
|
||||
end
|
||||
|
||||
def test_wait_interruption
|
||||
queue = Queue.new
|
||||
cond = @monitor.new_cond
|
||||
@monitor.define_singleton_method(:mon_enter_for_cond) do |*args|
|
||||
queue.deq
|
||||
super(*args)
|
||||
end
|
||||
th = Thread.start {
|
||||
@monitor.synchronize do
|
||||
begin
|
||||
cond.wait(0.1)
|
||||
rescue Interrupt
|
||||
@monitor.instance_variable_get(:@mon_owner)
|
||||
end
|
||||
end
|
||||
}
|
||||
sleep(0.1)
|
||||
th.raise(Interrupt)
|
||||
queue.enq(nil)
|
||||
assert_equal th, th.value
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue