aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/lib/active_support/concurrency/share_lock.rb10
-rw-r--r--activesupport/test/share_lock_test.rb21
2 files changed, 27 insertions, 4 deletions
diff --git a/activesupport/lib/active_support/concurrency/share_lock.rb b/activesupport/lib/active_support/concurrency/share_lock.rb
index 39ae9bfb79..ca48164c54 100644
--- a/activesupport/lib/active_support/concurrency/share_lock.rb
+++ b/activesupport/lib/active_support/concurrency/share_lock.rb
@@ -54,10 +54,12 @@ module ActiveSupport
loose_shares = @sharing.delete(Thread.current)
@waiting[Thread.current] = compatible if loose_shares
- @cv.wait_while { busy?(purpose) }
-
- @waiting.delete Thread.current
- @sharing[Thread.current] = loose_shares if loose_shares
+ begin
+ @cv.wait_while { busy?(purpose) }
+ ensure
+ @waiting.delete Thread.current
+ @sharing[Thread.current] = loose_shares if loose_shares
+ end
end
@exclusive_thread = Thread.current
end
diff --git a/activesupport/test/share_lock_test.rb b/activesupport/test/share_lock_test.rb
index efd840be79..4c0d23784e 100644
--- a/activesupport/test/share_lock_test.rb
+++ b/activesupport/test/share_lock_test.rb
@@ -81,6 +81,27 @@ class ShareLockTest < ActiveSupport::TestCase
end
end
+ def test_killed_thread_loses_lock
+ with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|
+ thread = Thread.new do
+ @lock.sharing do
+ @lock.exclusive {}
+ end
+ end
+
+ assert_threads_stuck thread
+ thread.kill
+
+ sharing_thread_release_latch.count_down
+
+ thread = Thread.new do
+ @lock.exclusive {}
+ end
+
+ assert_threads_not_stuck thread
+ end
+ end
+
def test_exclusive_conflicting_purpose
[true, false].each do |use_upgrading|
with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|