1
0
Fork 0
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:
shugo 2018-11-28 01:51:44 +00:00
parent db7338fd75
commit 6ec1720aa3
2 changed files with 33 additions and 7 deletions

View file

@ -103,15 +103,19 @@ module MonitorMixin
# even if no other thread doesn't signal.
#
def wait(timeout = nil)
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
#
# Calls wait repeatedly while the given block yields a truthy value.

View file

@ -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