Skip to content

Commit 3ac8cc4

Browse files
committed
[GR-18163] Fix usage of Thread.handle_interrupt in MonitorMixin#mon_synchronize
PullRequest: truffleruby/2468
2 parents 0d35a7b + 2053aea commit 3ac8cc4

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Bug fixes:
1717
* Fix handling of signals with `--single-threaded` (#2265).
1818
* Fix `Enumerator::Lazy#{chunk_while, slice_before, slice_after, slice_when}` to return instances of `Enumerator::Lazy` (#2273).
1919
* Fix `Truffle::Interop.source_location` to return unavailable source sections for modules instead of null (#2257).
20+
* Fix usage of `Thread.handle_interrupt` in `MonitorMixin#mon_synchronize`.
2021

2122
Compatibility:
2223

lib/mri/monitor.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,15 @@ def mon_owned?
230230
def mon_synchronize
231231
# Prevent interrupt on handling interrupts; for example timeout errors
232232
# it may break locking state.
233-
Thread.handle_interrupt(EXCEPTION_NEVER){ mon_enter }
234-
begin
235-
yield
236-
ensure
237-
Thread.handle_interrupt(EXCEPTION_NEVER){ mon_exit }
233+
Thread.handle_interrupt(EXCEPTION_NEVER) do
234+
mon_enter
235+
begin
236+
Thread.handle_interrupt(EXCEPTION_IMMEDIATE) do
237+
yield
238+
end
239+
ensure
240+
mon_exit
241+
end
238242
end
239243
end
240244
alias synchronize mon_synchronize
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
require_relative '../../spec_helper'
2+
require 'monitor'
3+
4+
describe "Monitor#synchronize" do
5+
it "unlocks after return, even if it was interrupted by Thread#raise" do
6+
exc_class = Class.new(RuntimeError)
7+
8+
monitor = Monitor.new
9+
10.times do
10+
locked = false
11+
12+
thread = Thread.new do
13+
begin
14+
monitor.synchronize do
15+
locked = true
16+
# Do not wait here, we are trying to interrupt the ensure part of #synchronize
17+
end
18+
sleep # wait for exception if it did not happen yet
19+
rescue exc_class
20+
monitor.should_not.mon_locked?
21+
:ok
22+
end
23+
end
24+
25+
Thread.pass until locked
26+
thread.raise exc_class, "interrupt"
27+
thread.value.should == :ok
28+
end
29+
end
30+
end

0 commit comments

Comments
 (0)