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

ruby-changes:56353

From: Nobuyoshi <ko1@a...>
Date: Wed, 3 Jul 2019 04:26:56 +0900 (JST)
Subject: [ruby-changes:56353] Nobuyoshi Nakada: 796eeb6339 (master): Fix up [Feature #15974]

https://git.ruby-lang.org/ruby.git/commit/?id=796eeb6339

From 796eeb6339952d92ae1b353d450c7883e589852d Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Wed, 3 Jul 2019 04:12:20 +0900
Subject: Fix up [Feature #15974]

* Fixed warning condition
* Fixed function signature
* Use ident hash

diff --git a/gc.c b/gc.c
index bb6b0d8..2f6983e 100644
--- a/gc.c
+++ b/gc.c
@@ -2961,8 +2961,9 @@ struct should_not_capture_data { https://github.com/ruby/ruby/blob/trunk/gc.c#L2961
 };
 
 static void
-should_not_capture_callback(const VALUE child, struct should_not_capture_data *data)
+should_not_capture_callback(VALUE child, void *dp)
 {
+    struct should_not_capture_data *data = dp;
     if (child == data->obj)
 	data->found = true;
 
@@ -2970,22 +2971,20 @@ should_not_capture_callback(const VALUE child, struct should_not_capture_data *d https://github.com/ruby/ruby/blob/trunk/gc.c#L2971
 	return;
 
     // Maintain a set of objects already searched, so that we don't follow a cycle
-    VALUE key = rb_obj_id(child);
-    if (rb_hash_has_key(data->set, key))
+    if (rb_hash_lookup2(data->set, child, Qfalse))
 	return;
-    rb_hash_aset(data->set, key, Qtrue);
+    rb_hash_aset(data->set, child, Qtrue);
 
-    rb_objspace_reachable_objects_from(child, (void (*)(unsigned long, void *)) &should_not_capture_callback, (void *)data);
+    rb_objspace_reachable_objects_from(child, should_not_capture_callback, data);
 }
 
 static void
 should_not_capture(VALUE block, VALUE obj)
 {
-    struct should_not_capture_data data;
-    data.obj = obj;
-    data.set = rb_hash_new();
-    data.found = false;
-    rb_objspace_reachable_objects_from(block, (void (*)(unsigned long, void *)) &should_not_capture_callback, (void *)&data);
+    struct should_not_capture_data data = {obj, rb_ident_hash_new()};
+    rb_obj_hide(data.set);
+    rb_objspace_reachable_objects_from(block, should_not_capture_callback, &data);
+    rb_hash_clear(data.set);
     if (data.found)
 	rb_warn("object is reachable from finalizer - it may never be run");
 }
@@ -3019,8 +3018,9 @@ define_final(int argc, VALUE *argv, VALUE os) https://github.com/ruby/ruby/blob/trunk/gc.c#L3018
 	should_be_callable(block);
     }
 
-    if (ruby_verbose)
+    if (RTEST(ruby_verbose)) {
 	should_not_capture(block, obj);
+    }
 
     return define_final0(obj, block);
 }
diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb
index c352b75..9007e05 100644
--- a/test/ruby/test_objectspace.rb
+++ b/test/ruby/test_objectspace.rb
@@ -56,7 +56,7 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_objectspace.rb#L56
   end
 
   def test_finalizer
-    assert_in_out_err(["-e", <<-END], "", %w(:ok :ok :ok :ok), [])
+    assert_in_out_err(["-W0", "-e", <<-END], "", %w(:ok :ok :ok :ok))
       a = []
       ObjectSpace.define_finalizer(a) { p :ok }
       b = a.dup
@@ -76,8 +76,8 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_objectspace.rb#L76
       ObjectSpace.define_finalizer([], fin)
       CODE
     end
-    assert_in_out_err([], code[""], ["finalized"])
-    assert_in_out_err([], code["private "], ["finalized"])
+    assert_in_out_err(["-W0"], code[""], ["finalized"])
+    assert_in_out_err(["-W0"], code["private "], ["finalized"])
     c = EnvUtil.labeled_class("C\u{3042}").new
     o = Object.new
     assert_raise_with_message(ArgumentError, /C\u{3042}/) {
@@ -131,6 +131,32 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_objectspace.rb#L131
     END
   end
 
+  def test_self_referencing_finalizer
+    assert_separately(["-w"], "#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      obj = +"Test"
+      handler = proc {puts "finalized"}
+      assert_warning(/object is reachable from finalizer/) do
+        ObjectSpace.define_finalizer(obj, handler)
+      end
+    end;
+  end
+
+  def test_indirectly_self_referencing_finalizer
+    assert_separately(["-w"], "#{<<~"begin;"}\n#{<<~'end;'}")
+    begin;
+      def scoped(indirect)
+        proc {puts "finalized"}
+      end
+      obj = +"Test"
+      indirect = [obj]
+      handler = scoped(indirect)
+      assert_warning(/object is reachable from finalizer/) do
+        ObjectSpace.define_finalizer(obj, handler)
+      end
+    end;
+  end
+
   def test_each_object
     klass = Class.new
     new_obj = klass.new
-- 
cgit v0.10.2


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

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