summaryrefslogtreecommitdiff
path: root/spec/ruby
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-17 09:51:26 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-17 09:51:26 +0000
commit3993cd8058f7cc1032b289a357d31145f84427ac (patch)
treee513969a04d4ea83477bcff068aa7312aceb6414 /spec/ruby
parent30ad34297562e6f7cf2bc050b8d966743cbaff6e (diff)
Integrate new specs for ConditionVariable#wait to prevent regressions
* See [Bug #14999]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64409 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby')
-rw-r--r--spec/ruby/library/conditionvariable/wait_spec.rb96
1 files changed, 96 insertions, 0 deletions
diff --git a/spec/ruby/library/conditionvariable/wait_spec.rb b/spec/ruby/library/conditionvariable/wait_spec.rb
index 6209f5b2b8..d4950a7b27 100644
--- a/spec/ruby/library/conditionvariable/wait_spec.rb
+++ b/spec/ruby/library/conditionvariable/wait_spec.rb
@@ -22,4 +22,100 @@ describe "ConditionVariable#wait" do
m.synchronize { cv.signal }
th.join
end
+
+ it "reacquires the lock even if the thread is killed" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+ owned = nil
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ begin
+ cv.wait(m)
+ ensure
+ owned = m.owned?
+ $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
+ end
+ end
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass while th.status and th.status != "sleep"
+
+ th.kill
+ th.join
+
+ owned.should == true
+ end
+
+ it "reacquires the lock even if the thread is killed after being signaled" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+ owned = nil
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ begin
+ cv.wait(m)
+ ensure
+ owned = m.owned?
+ $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
+ end
+ end
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass while th.status and th.status != "sleep"
+
+ m.synchronize {
+ cv.signal
+ # Wait that the thread is blocked on acquiring the Mutex
+ sleep 0.001
+ # Kill the thread, yet the thread should first acquire the Mutex before going on
+ th.kill
+ }
+
+ th.join
+ owned.should == true
+ end
+
+ it "supports multiple Threads waiting on the same ConditionVariable and Mutex" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ n_threads = 4
+ events = []
+
+ threads = n_threads.times.map {
+ Thread.new {
+ m.synchronize {
+ events << :t_in_synchronize
+ cv.wait(m)
+ }
+ }
+ }
+
+ Thread.pass until m.synchronize { events.size } == n_threads
+ Thread.pass while threads.any? { |th| th.status and th.status != "sleep" }
+ m.synchronize do
+ threads.each { |t|
+ # Cause interactions with the waiting threads.
+ # On TruffleRuby, this causes a safepoint which has interesting
+ # interactions with the ConditionVariable.
+ bt = t.backtrace
+ bt.should be_kind_of(Array)
+ bt.size.should >= 2
+ }
+ end
+
+ cv.broadcast
+ threads.each(&:join)
+ end
end