summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-04-07 11:32:30 -0700
committerJeremy Evans <code@jeremyevans.net>2021-07-29 09:44:11 -0700
commit87b327efe6c1f456c43b3f105c7a92a5a7effe93 (patch)
tree11c691d62096b0dd5b2d8105a86c947f3943ce55
parentcbecf9c7ba71ef0e844c72c97f85ce4fffb46aa6 (diff)
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>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4366
-rw-r--r--gc.c4
-rw-r--r--test/ruby/test_objectspace.rb25
2 files changed, 29 insertions, 0 deletions
diff --git a/gc.c b/gc.c
index da0f5ff1b2..f6ea4fc6de 100644
--- a/gc.c
+++ b/gc.c
@@ -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
diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb
index c26748f516..7d4a773d4b 100644
--- a/test/ruby/test_objectspace.rb
+++ b/test/ruby/test_objectspace.rb
@@ -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