aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test/share_lock_test.rb
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-02-07 08:24:57 +1030
committerMatthew Draper <matthew@trebex.net>2016-02-07 08:32:27 +1030
commit3e4a69e52d8c8f0335e0ddbb46fe21009b962334 (patch)
tree172481e3ea5e3ed7496ff2541a595343fbd49ae8 /activesupport/test/share_lock_test.rb
parent8526e9bed21a119266e886c3316d3fe10c9af5ce (diff)
downloadrails-3e4a69e52d8c8f0335e0ddbb46fe21009b962334.tar.gz
rails-3e4a69e52d8c8f0335e0ddbb46fe21009b962334.tar.bz2
rails-3e4a69e52d8c8f0335e0ddbb46fe21009b962334.zip
Hand off the interlock to the new thread in AC::Live
Most importantly, the original request thread must yield its share lock while waiting for the live thread to commit -- otherwise a request's base and live threads can deadlock against each other.
Diffstat (limited to 'activesupport/test/share_lock_test.rb')
-rw-r--r--activesupport/test/share_lock_test.rb26
1 files changed, 26 insertions, 0 deletions
diff --git a/activesupport/test/share_lock_test.rb b/activesupport/test/share_lock_test.rb
index 12953d99a6..68fa5bb69e 100644
--- a/activesupport/test/share_lock_test.rb
+++ b/activesupport/test/share_lock_test.rb
@@ -287,6 +287,32 @@ class ShareLockTest < ActiveSupport::TestCase
assert_threads_not_stuck threads
end
+ def test_manual_yield
+ ready = Concurrent::CyclicBarrier.new(2)
+ done = Concurrent::CyclicBarrier.new(2)
+
+ threads = [
+ Thread.new do
+ @lock.sharing do
+ ready.wait
+ @lock.exclusive(purpose: :x) {}
+ done.wait
+ end
+ end,
+
+ Thread.new do
+ @lock.sharing do
+ ready.wait
+ @lock.yield_shares(compatible: [:x]) do
+ done.wait
+ end
+ end
+ end,
+ ]
+
+ assert_threads_not_stuck threads
+ end
+
def test_in_shared_section_incompatible_non_upgrading_threads_cannot_preempt_upgrading_threads
scratch_pad = []
scratch_pad_mutex = Mutex.new