variable.c: fix autoload object lifetimes and leak
We must not call normal Hash methods inside GC free callback, either, however identity hash may be used. [ruby-core:86935] [Bug #14742] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63389 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
23c74845ed
commit
6726038d76
@ -335,6 +335,18 @@ p Foo::Bar
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_no_leak
|
||||||
|
assert_no_memory_leak([], '', <<~'end;', 'many autoloads', timeout: 30)
|
||||||
|
200000.times do |i|
|
||||||
|
m = Module.new
|
||||||
|
m.instance_eval do
|
||||||
|
autoload :Foo, 'x'
|
||||||
|
autoload :Bar, i.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
|
||||||
def add_autoload(path)
|
def add_autoload(path)
|
||||||
(@autoload_paths ||= []) << path
|
(@autoload_paths ||= []) << path
|
||||||
::Object.class_eval {autoload(:AutoloadTest, path)}
|
::Object.class_eval {autoload(:AutoloadTest, path)}
|
||||||
|
13
variable.c
13
variable.c
@ -1908,6 +1908,7 @@ autoload_c_free(void *ptr)
|
|||||||
{
|
{
|
||||||
struct autoload_const *ac = ptr;
|
struct autoload_const *ac = ptr;
|
||||||
list_del(&ac->cnode);
|
list_del(&ac->cnode);
|
||||||
|
xfree(ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
@ -1990,7 +1991,7 @@ rb_autoload_str(VALUE mod, ID id, VALUE file)
|
|||||||
}
|
}
|
||||||
file = rb_fstring(file);
|
file = rb_fstring(file);
|
||||||
if (!autoload_featuremap) {
|
if (!autoload_featuremap) {
|
||||||
autoload_featuremap = rb_hash_new();
|
autoload_featuremap = rb_hash_new_compare_by_id();
|
||||||
rb_obj_hide(autoload_featuremap);
|
rb_obj_hide(autoload_featuremap);
|
||||||
rb_gc_register_mark_object(autoload_featuremap);
|
rb_gc_register_mark_object(autoload_featuremap);
|
||||||
}
|
}
|
||||||
@ -2036,13 +2037,13 @@ autoload_delete(VALUE mod, ID id)
|
|||||||
ele = get_autoload_data((VALUE)load, &ac);
|
ele = get_autoload_data((VALUE)load, &ac);
|
||||||
VM_ASSERT(!list_empty(&ele->constants));
|
VM_ASSERT(!list_empty(&ele->constants));
|
||||||
|
|
||||||
/* list_del_init to make list_del in autoload_c_free idempotent: */
|
/*
|
||||||
|
* we must delete here to avoid "already initialized" warnings
|
||||||
|
* with parallel autoload. list_del_init makes list_del in
|
||||||
|
* autoload_c_free idempotent
|
||||||
|
*/
|
||||||
list_del_init(&ac->cnode);
|
list_del_init(&ac->cnode);
|
||||||
|
|
||||||
if (list_empty(&ele->constants)) {
|
|
||||||
rb_hash_delete(autoload_featuremap, ele->feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tbl->num_entries == 0) {
|
if (tbl->num_entries == 0) {
|
||||||
n = autoload;
|
n = autoload;
|
||||||
st_delete(RCLASS_IV_TBL(mod), &n, &val);
|
st_delete(RCLASS_IV_TBL(mod), &n, &val);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user