From 6e8b68a98887093fe5f3cce1ad0ca390e19a9e25 Mon Sep 17 00:00:00 2001 From: Songstats Dependency Audit Date: Sat, 29 Aug 2026 22:54:40 +0200 Subject: [PATCH 1/2] Release TVar locks for all exceptions --- lib/concurrent-ruby/concurrent/tvar.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/concurrent-ruby/concurrent/tvar.rb b/lib/concurrent-ruby/concurrent/tvar.rb index 5d02ef090..ef9168aa8 100644 --- a/lib/concurrent-ruby/concurrent/tvar.rb +++ b/lib/concurrent-ruby/concurrent/tvar.rb @@ -111,7 +111,7 @@ def atomically rescue Transaction::LeaveError => e transaction.abort break result - rescue => e + rescue Exception => e transaction.abort raise e end From 8ae804a289bd0a26fe35c9cfc651b1f10aab23c9 Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Sun, 30 Aug 2026 15:06:45 +0700 Subject: [PATCH 2/2] Test TVar cleanup for nonstandard exceptions --- lib/concurrent-ruby/concurrent/tvar.rb | 4 ++-- spec/concurrent/tvar_spec.rb | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/concurrent-ruby/concurrent/tvar.rb b/lib/concurrent-ruby/concurrent/tvar.rb index ef9168aa8..b74417d7d 100644 --- a/lib/concurrent-ruby/concurrent/tvar.rb +++ b/lib/concurrent-ruby/concurrent/tvar.rb @@ -111,9 +111,9 @@ def atomically rescue Transaction::LeaveError => e transaction.abort break result - rescue Exception => e + rescue Exception transaction.abort - raise e + raise end # If we can commit, break out of the loop diff --git a/spec/concurrent/tvar_spec.rb b/spec/concurrent/tvar_spec.rb index 437ff5788..d1a2e3318 100644 --- a/spec/concurrent/tvar_spec.rb +++ b/spec/concurrent/tvar_spec.rb @@ -48,6 +48,22 @@ module Concurrent }.to raise_error(StandardError, 'This is an error!') end + it 'aborts and releases locks for exceptions outside StandardError' do + t = TVar.new(0) + error = Interrupt.new('This is an interrupt!') + + expect { + Concurrent::atomically do + t.value = 1 + raise error + end + }.to raise_error(error) + + expect(t.value).to eq 0 + expect { Concurrent::atomically { t.value = 2 } }.not_to raise_error + expect(t.value).to eq 2 + end + it 'retries on abort' do count = 0