ruby-changes:56365
From: Nobuyoshi <ko1@a...>
Date: Thu, 4 Jul 2019 04:04:17 +0900 (JST)
Subject: [ruby-changes:56365] Nobuyoshi Nakada: 23c92b6f82 (master): Revert self-referencing finalizer warning [Feature #15974]
https://git.ruby-lang.org/ruby.git/commit/?id=23c92b6f82 From 23c92b6f820f670994026423d4c7b5abcf51eafa Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Wed, 3 Jul 2019 14:44:20 +0900 Subject: Revert self-referencing finalizer warning [Feature #15974] It has caused CI failures. * d0cd0866d82a58933e5dccd073c753c0c2ad4eb5 Disable GC during rb_objspace_reachable_object_p * 89cef1c56b3a0f9c5e6ccc22a5044477a4fd16c1 Version guard for [Feature #15974] * 796eeb6339952d92ae1b353d450c7883e589852d. Fix up [Feature #15974] * 928260c2a613bbdd4402c300e0bf86ae7562e52a. Warn in verbose mode on defining a finalizer that captures the object diff --git a/gc.c b/gc.c index 084923f..2b7b039 100644 --- a/gc.c +++ b/gc.c @@ -2954,8 +2954,6 @@ should_be_finalizable(VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L2954 rb_check_frozen(obj); } -static int rb_objspace_reachable_object_p(VALUE obj, VALUE root); - /* * call-seq: * ObjectSpace.define_finalizer(obj, aProc=proc()) @@ -2965,10 +2963,6 @@ static int rb_objspace_reachable_object_p(VALUE obj, VALUE root); https://github.com/ruby/ruby/blob/trunk/gc.c#L2963 * as an argument to <i>aProc</i>. If <i>aProc</i> is a lambda or * method, make sure it can be called with a single argument. * - * In verbose mode (<code>-w</code>) a warning will be issued if - * the object is reachable from <i>aProc</i>, which may prevent - * finalization. - * */ static VALUE @@ -2985,11 +2979,6 @@ define_final(int argc, VALUE *argv, VALUE os) https://github.com/ruby/ruby/blob/trunk/gc.c#L2979 should_be_callable(block); } - if (RTEST(ruby_verbose)) { - if (rb_objspace_reachable_object_p(obj, block)) - rb_warn("object is reachable from finalizer - it may never be run"); - } - return define_final0(obj, block); } @@ -9337,59 +9326,6 @@ rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, https://github.com/ruby/ruby/blob/trunk/gc.c#L9326 POP_MARK_FUNC_DATA(); } -struct reachable_object_data { - VALUE obj; - VALUE set; -}; - -static void -reachable_object_callback(VALUE child, void *dp) -{ - struct reachable_object_data *data = dp; - if (child == data->obj) { - rb_throw_obj(data->set, Qtrue); - } - - // Maintain a set of objects already searched, so that we don't follow a cycle - if (rb_hash_lookup2(data->set, child, Qfalse)) - return; - rb_hash_aset(data->set, child, Qtrue); - - rb_objspace_reachable_objects_from(child, reachable_object_callback, data); -} - -static VALUE -call_reachable_object(RB_BLOCK_CALL_FUNC_ARGLIST(set, arg)) -{ - struct reachable_object_data *data = (void *)arg; - VALUE obj = data->set; - data->set = rb_obj_hide(set); - gc_mark_children(&rb_objspace, obj); - rb_hash_clear(set); - return Qfalse; -} - -static int -rb_objspace_reachable_object_p(VALUE obj, VALUE root) -{ - rb_objspace_t *objspace = &rb_objspace; - int reachable = FALSE; - if (is_markable_object(objspace, obj)) { - struct reachable_object_data data = {obj, root}; - struct mark_func_data_struct mfd = {&data, reachable_object_callback}; - int prev_dont_gc = dont_gc; - enum ruby_tag_type state; - - dont_gc = TRUE; - PUSH_MARK_FUNC_DATA(&mfd); - reachable = RTEST(rb_catch_protect(rb_ident_hash_new(), call_reachable_object, (VALUE)&data, &state)); - POP_MARK_FUNC_DATA(); - dont_gc = prev_dont_gc; - if (state) EC_JUMP_TAG(GET_EC(), state); - } - return reachable; -} - /* ------------------------ Extended allocator ------------------------ */ diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb index fef7667..b7e4747 100644 --- a/spec/ruby/core/objectspace/define_finalizer_spec.rb +++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb @@ -65,32 +65,4 @@ describe "ObjectSpace.define_finalizer" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/objectspace/define_finalizer_spec.rb#L65 ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"] end - - ruby_version_is "2.7" do - it "warns in verbose mode if it is self-referencing" do - code = <<-RUBY - obj = "Test" - handler = Proc.new { puts "finalized" } - ObjectSpace.define_finalizer(obj, handler) - exit 0 - RUBY - - ruby_exe(code, :options => "-w", :args => "2>&1").should include("warning: object is reachable from finalizer - it may never be run") - end - - it "warns in verbose mode if it is indirectly self-referencing" do - code = <<-RUBY - def scoped(indirect) - Proc.new { puts "finalized" } - end - obj = "Test" - indirect = [obj] - handler = scoped(indirect) - ObjectSpace.define_finalizer(obj, handler) - exit 0 - RUBY - - ruby_exe(code, :options => "-w", :args => "2>&1").should include("warning: object is reachable from finalizer - it may never be run") - end - end end diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb index 9007e05..c352b75 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(["-W0", "-e", <<-END], "", %w(:ok :ok :ok :ok)) + assert_in_out_err(["-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(["-W0"], code[""], ["finalized"]) - assert_in_out_err(["-W0"], code["private "], ["finalized"]) + assert_in_out_err([], code[""], ["finalized"]) + assert_in_out_err([], code["private "], ["finalized"]) c = EnvUtil.labeled_class("C\u{3042}").new o = Object.new assert_raise_with_message(ArgumentError, /C\u{3042}/) { @@ -131,32 +131,6 @@ 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/