Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit 708d217

Browse files
committed
Use Mutex#owned? to correctly check if the Mutex is owned by the current Thread or Fiber
* In Ruby >= 3, Mutex are held per Fiber, not per Thread. * Fixes #501
1 parent b3563f1 commit 708d217

File tree

2 files changed

+29
-6
lines changed

2 files changed

+29
-6
lines changed

lib/rspec/support/reentrant_mutex.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ class << self
1717
# @private
1818
class ReentrantMutex
1919
def initialize
20-
@owner = nil
2120
@count = 0
2221
@mutex = Mutex.new
2322
end
@@ -32,16 +31,16 @@ def synchronize
3231
private
3332

3433
def enter
35-
@mutex.lock if @owner != Thread.current
36-
@owner = Thread.current
34+
@mutex.lock unless @mutex.owned?
3735
@count += 1
3836
end
3937

4038
def exit
39+
unless @mutex.owned?
40+
raise ThreadError, "Attempt to unlock a mutex which is locked by another thread/fiber"
41+
end
4142
@count -= 1
42-
return unless @count == 0
43-
@owner = nil
44-
@mutex.unlock
43+
@mutex.unlock if @count == 0
4544
end
4645
end
4746
end

spec/rspec/support/reentrant_mutex_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,28 @@
3434
mutex.synchronize { order.pass_to :thread, :resume_on => :sleep }
3535
order.join_all
3636
end
37+
38+
if RUBY_VERSION >= '3.0'
39+
it 'waits when trying to lock from another Fiber' do
40+
mutex.synchronize do
41+
ready = false
42+
f = Fiber.new do
43+
expect {
44+
ready = true
45+
mutex.send(:enter)
46+
raise 'should reach here: mutex is already locked on different Fiber'
47+
}.to raise_error(Exception, 'waited correctly')
48+
end
49+
50+
main_thread = Thread.current
51+
52+
t = Thread.new do
53+
Thread.pass until ready and main_thread.stop?
54+
main_thread.raise Exception, 'waited correctly'
55+
end
56+
f.resume
57+
t.join
58+
end
59+
end
60+
end
3761
end

0 commit comments

Comments
 (0)