mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Fix up [Feature #15974]
* Fixed warning condition * Fixed function signature * Use ident hash
This commit is contained in:
parent
928260c2a6
commit
796eeb6339
2 changed files with 40 additions and 14 deletions
22
gc.c
22
gc.c
|
@ -2961,8 +2961,9 @@ struct should_not_capture_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
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)
|
if (child == data->obj)
|
||||||
data->found = true;
|
data->found = true;
|
||||||
|
|
||||||
|
@ -2970,22 +2971,20 @@ should_not_capture_callback(const VALUE child, struct should_not_capture_data *d
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Maintain a set of objects already searched, so that we don't follow a cycle
|
// Maintain a set of objects already searched, so that we don't follow a cycle
|
||||||
VALUE key = rb_obj_id(child);
|
if (rb_hash_lookup2(data->set, child, Qfalse))
|
||||||
if (rb_hash_has_key(data->set, key))
|
|
||||||
return;
|
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
|
static void
|
||||||
should_not_capture(VALUE block, VALUE obj)
|
should_not_capture(VALUE block, VALUE obj)
|
||||||
{
|
{
|
||||||
struct should_not_capture_data data;
|
struct should_not_capture_data data = {obj, rb_ident_hash_new()};
|
||||||
data.obj = obj;
|
rb_obj_hide(data.set);
|
||||||
data.set = rb_hash_new();
|
rb_objspace_reachable_objects_from(block, should_not_capture_callback, &data);
|
||||||
data.found = false;
|
rb_hash_clear(data.set);
|
||||||
rb_objspace_reachable_objects_from(block, (void (*)(unsigned long, void *)) &should_not_capture_callback, (void *)&data);
|
|
||||||
if (data.found)
|
if (data.found)
|
||||||
rb_warn("object is reachable from finalizer - it may never be run");
|
rb_warn("object is reachable from finalizer - it may never be run");
|
||||||
}
|
}
|
||||||
|
@ -3019,8 +3018,9 @@ define_final(int argc, VALUE *argv, VALUE os)
|
||||||
should_be_callable(block);
|
should_be_callable(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ruby_verbose)
|
if (RTEST(ruby_verbose)) {
|
||||||
should_not_capture(block, obj);
|
should_not_capture(block, obj);
|
||||||
|
}
|
||||||
|
|
||||||
return define_final0(obj, block);
|
return define_final0(obj, block);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ End
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_finalizer
|
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 = []
|
a = []
|
||||||
ObjectSpace.define_finalizer(a) { p :ok }
|
ObjectSpace.define_finalizer(a) { p :ok }
|
||||||
b = a.dup
|
b = a.dup
|
||||||
|
@ -76,8 +76,8 @@ End
|
||||||
ObjectSpace.define_finalizer([], fin)
|
ObjectSpace.define_finalizer([], fin)
|
||||||
CODE
|
CODE
|
||||||
end
|
end
|
||||||
assert_in_out_err([], code[""], ["finalized"])
|
assert_in_out_err(["-W0"], code[""], ["finalized"])
|
||||||
assert_in_out_err([], code["private "], ["finalized"])
|
assert_in_out_err(["-W0"], code["private "], ["finalized"])
|
||||||
c = EnvUtil.labeled_class("C\u{3042}").new
|
c = EnvUtil.labeled_class("C\u{3042}").new
|
||||||
o = Object.new
|
o = Object.new
|
||||||
assert_raise_with_message(ArgumentError, /C\u{3042}/) {
|
assert_raise_with_message(ArgumentError, /C\u{3042}/) {
|
||||||
|
@ -131,6 +131,32 @@ End
|
||||||
END
|
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
|
def test_each_object
|
||||||
klass = Class.new
|
klass = Class.new
|
||||||
new_obj = klass.new
|
new_obj = klass.new
|
||||||
|
|
Loading…
Reference in a new issue