< :前の番号
^ :番号順リスト
> :次の番号
P :前の記事(スレッド移動)
N :次の記事(スレッド移動)
|<:前のスレッド
>|:次のスレッド
^ :返事先
_:自分への返事
>:同じ返事先を持つ記事(前)
<:同じ返事先を持つ記事(後)
---:分割してスレッド表示、再表示
| :分割して(縦)スレッド表示、再表示
~ :スレッドのフレーム消去
.:インデックス
..:インデックスのインデックス
Issue #15507 has been updated by larskanis (Lars Kanis).
The other two issues are #15508 and #15509 .
----------------------------------------
Bug #15507: Thread#raise is delivered to GC context
https://bugs.ruby-lang.org/issues/15507#change-76083
* Author: larskanis (Lars Kanis)
* Status: Open
* Priority: Normal
* Assignee:
* Target version:
* ruby -v: ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux]
* Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
Since I started the development of [Eventbox](https://github.com/larskanis/eventbox) I noticed sporadic failures of the Eventbox test suite on MRI. [One issue](https://github.com/larskanis/eventbox/issues/2) has been fixed in the meantime, but I was now able to minimize 3 others to a reproducible script. This is the first one:
This script combines a GC finalizer with Thread#raise:
```ruby
Thread.abort_on_exception = true
class Finalizer
def self.define
ObjectSpace.define_finalizer(String.new, self.method(:gc))
end
def self.gc(object_id)
puts "gc #{object_id} #{caller[0]}"
end
end
class Deadlocker
class Stop < RuntimeError
end
def self.run
th = Thread.handle_interrupt(Exception => :never) do
Thread.new do
begin
Thread.handle_interrupt(Stop => :on_blocking) do
100.times { String.new } # Trigger GC
sleep 5 # Wait for Stop exception
raise "not interrupted"
end
rescue Stop
end
end
end
th.raise Stop
th.join
end
end
100.times do
Finalizer.define # This alone works well
Deadlocker.run # This alone works equally, but both interfere badly
end
```
The program output looks similar to:
```ruby
$ ruby -d --disable-gems interrupt-in-gc-error.rb
Exception `Deadlocker::Stop' at interrupt-in-gc-error.rb:23 - Deadlocker::Stop
Exception `Deadlocker::Stop' at interrupt-in-gc-error.rb:23 - Deadlocker::Stop
[...]
Exception `Deadlocker::Stop' at interrupt-in-gc-error.rb:9 - Deadlocker::Stop
gc 47133824012760 interrupt-in-gc-error.rb:22:in `call'
gc 47133824022800 interrupt-in-gc-error.rb:22:in `call'
[...]
Exception `RuntimeError' at interrupt-in-gc-error.rb:24 - not interrupted
#<Thread:0x000055bc65ac8f38 / interrupt-in-gc-error.rb:19 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
2: from interrupt-in-gc-error.rb:21:in `block (2 levels) in run'
1: from interrupt-in-gc-error.rb:21:in `handle_interrupt'
interrupt-in-gc-error.rb:24:in `block (3 levels) in run': not interrupted (RuntimeError)
```
The debug output shows, that the `Stop` exception is delivered several times, so that the sleep call is properly interrupted. But if the interrupt is sent just in the moment when the finalizer is active, it is discarded and doesn't abort the `sleep` call.
IMHO interrupts shouldn't be delivered to any GC/trap context. At least they should be masked in this context.
This issue is present on all older MRI versions. However it doesn't appear on JRuby-9.2.5.0. So they seem to have solved the GC/interrupt relationship somehow.
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>