[前][次][番号順一覧][スレッド一覧]

ruby-changes:66982

From: Jeremy <ko1@a...>
Date: Fri, 30 Jul 2021 01:44:34 +0900 (JST)
Subject: [ruby-changes:66982] 87b327efe6 (master): Do not check pending interrupts when running finalizers

https://git.ruby-lang.org/ruby.git/commit/?id=87b327efe6

From 87b327efe6c1f456c43b3f105c7a92a5a7effe93 Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@j...>
Date: Wed, 7 Apr 2021 11:32:30 -0700
Subject: 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@a...>
---
 gc.c                          |  4 ++++
 test/ruby/test_objectspace.rb | 25 +++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/gc.c b/gc.c
index da0f5ff..f6ea4fc 100644
--- a/gc.c
+++ b/gc.c
@@ -4088,10 +4088,14 @@ static void https://github.com/ruby/ruby/blob/trunk/gc.c#L4088
 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 c26748f..7d4a773 100644
--- a/test/ruby/test_objectspace.rb
+++ b/test/ruby/test_objectspace.rb
@@ -168,6 +168,31 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_objectspace.rb#L168
     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
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]