1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Do not check pending interrupts when running finalizers

This fixes cases where exceptions raised using Thread#raise are
swallowed by finalizers and not delivered to the running thread.

This could cause issues with finalizers that rely on pending interrupts,
but that case is expected to be rarer.

Fixes [Bug #13876]
Fixes [Bug #15507]

Co-authored-by: Koichi Sasada <ko1@atdot.net>
This commit is contained in:
Jeremy Evans 2021-04-07 11:32:30 -07:00
parent cbecf9c7ba
commit 87b327efe6
Notes: git 2021-07-30 01:44:40 +09:00
2 changed files with 29 additions and 0 deletions

4
gc.c
View file

@ -4088,10 +4088,14 @@ static void
finalize_deferred(rb_objspace_t *objspace)
{
VALUE zombie;
rb_execution_context_t *ec = GET_EC();
ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
while ((zombie = ATOMIC_VALUE_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
finalize_list(objspace, zombie);
}
ec->interrupt_mask &= ~PENDING_INTERRUPT_MASK;
}
static void

View file

@ -168,6 +168,31 @@ End
end;
end
def test_finalizer_thread_raise
GC.disable
fzer = proc do |id|
sleep 0.2
end
2.times do
o = Object.new
ObjectSpace.define_finalizer(o, fzer)
end
my_error = Class.new(RuntimeError)
begin
main_th = Thread.current
Thread.new do
sleep 0.1
main_th.raise(my_error)
end
GC.start
puts "After GC"
sleep(10)
assert(false)
rescue my_error
end
end
def test_each_object
klass = Class.new
new_obj = klass.new