Skip to content

Commit fd66320

Browse files
committed
Test thread interrupt during mutex lock
In jruby#9218 a user discovered that thread interrupt during an attempt to lock a mutex may render that mutex unusable from any other fiber, even if it did not successfully lock. This spec tries to trigger that state by having one thread loop while triggering a raise interrupt on another thread that repeatedly locks a mutex from within fibers. This may not always fail when it is broken due to the timing issues involved in triggering the interrupt after the lock was acquired but before interrupts have been handled by the fiber, but 10x seems sufficient to trigger the bug on JRuby.
1 parent acd6e8a commit fd66320

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

spec/ruby/core/mutex/lock_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,42 @@
4848
f1.resume
4949
-> { f2.resume }.should raise_error(ThreadError, /deadlock/)
5050
end
51+
52+
it "does not raise deadlock if a fiber's attempt to lock was interrupted" do
53+
lock = Mutex.new
54+
main = Thread.current
55+
56+
t2 = nil
57+
t1 = Thread.new do
58+
loop do
59+
# interrupt fiber below looping on synchronize
60+
sleep 0.01
61+
t2.raise if t2
62+
end
63+
end
64+
65+
# loop ten times to try to handle the interrupt during synchronize
66+
t2 = Thread.new do
67+
10.times do
68+
Fiber.new do
69+
begin
70+
loop { lock.synchronize {} }
71+
rescue RuntimeError
72+
end
73+
end.resume
74+
75+
Fiber.new do
76+
->() do
77+
lock.synchronize {}
78+
end.should_not raise_error(ThreadError)
79+
end.resume
80+
rescue RuntimeError
81+
retry
82+
end
83+
end
84+
t2.join
85+
ensure
86+
t1.kill rescue nil
87+
t2.kill rescue nil
88+
end
5189
end

0 commit comments

Comments
 (0)