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

Revert self-referencing finalizer warning [Feature #15974]

It has caused CI failures.

* d0cd0866d8

  Disable GC during rb_objspace_reachable_object_p

* 89cef1c56b

  Version guard for [Feature #15974]

* 796eeb6339.

  Fix up [Feature #15974]

* 928260c2a6.

  Warn in verbose mode on defining a finalizer that captures the object
This commit is contained in:
Nobuyoshi Nakada 2019-07-03 14:44:20 +09:00
parent 5d9e91afe0
commit 23c92b6f82
No known key found for this signature in database
GPG key ID: 4BC7D6DF58D8DF60
3 changed files with 3 additions and 121 deletions

64
gc.c
View file

@ -2954,8 +2954,6 @@ should_be_finalizable(VALUE obj)
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);
* 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)
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,
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 ------------------------
*/

View file

@ -65,32 +65,4 @@ describe "ObjectSpace.define_finalizer" do
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

View file

@ -56,7 +56,7 @@ End
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
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
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