diff options
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/concurrency/share_lock.rb | 10 | ||||
-rw-r--r-- | activesupport/test/share_lock_test.rb | 21 |
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| |