Created
September 20, 2011 02:40
-
-
Save mperham/1228184 to your computer and use it in GitHub Desktop.
ConditionVariables can wakeup threads that are no longer waiting on them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'thread' | |
# This shows how the main thread can be woken up by | |
# a condition variable that it is no longer waiting on. | |
# When waking up via timeout, the main thread is not removed | |
# from the waitlist and so gets a spurious wakeup from cond1 | |
# when it is no longer waiting on that variable. | |
# | |
# Result should be '2' but is actually '1' on Ruby 1.9.2. | |
# This code works on JRuby 1.6.4. | |
result = 'none' | |
puts Time.now.to_f | |
mutex1 = Mutex.new | |
cond1 = ConditionVariable.new | |
t1 = Thread.new do | |
sleep 0.5 | |
result = '1' | |
# this will signal the main thread when it is waiting on cond2 | |
cond1.signal | |
end | |
mutex1.synchronize do | |
cond1.wait(mutex1, 0.3) | |
end | |
puts Time.now.to_f | |
mutex2 = Mutex.new | |
cond2 = ConditionVariable.new | |
t2 = Thread.new do | |
sleep 0.5 | |
result = '2' | |
cond2.signal | |
end | |
mutex2.synchronize do | |
cond2.wait(mutex2, 1) | |
end | |
puts Time.now.to_f | |
puts result | |
raise ArgumentError, 'result != 2' if result != '2' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's the implementation of ConditionVariable#wait and ConditionVariable#signal for MRI 1.9.2. It looks like in #wait, if the timeout occurs, the Thread.current isn't removed from the @waiters array. So later on, in #signal, the old Thread.current instance is still in the @waiters array and gets notified even though it timed out!