mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Disable GC during rb_objspace_reachable_object_p
Try to fix CI breakage by [Feature #15974].
This commit is contained in:
parent
9f1d67a68f
commit
d0cd0866d8
1 changed files with 54 additions and 33 deletions
87
gc.c
87
gc.c
|
@ -2954,39 +2954,7 @@ should_be_finalizable(VALUE obj)
|
|||
rb_check_frozen(obj);
|
||||
}
|
||||
|
||||
struct reachable_object_data {
|
||||
VALUE obj;
|
||||
VALUE set;
|
||||
bool found;
|
||||
};
|
||||
|
||||
static void
|
||||
reachable_object_callback(VALUE child, void *dp)
|
||||
{
|
||||
struct reachable_object_data *data = dp;
|
||||
if (child == data->obj)
|
||||
data->found = true;
|
||||
|
||||
if (data->found)
|
||||
return;
|
||||
|
||||
// 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 int
|
||||
rb_objspace_reachable_object_p(VALUE obj, VALUE root)
|
||||
{
|
||||
struct reachable_object_data data = {obj, rb_ident_hash_new()};
|
||||
rb_obj_hide(data.set);
|
||||
rb_objspace_reachable_objects_from(root, reachable_object_callback, &data);
|
||||
rb_hash_clear(data.set);
|
||||
return data.found;
|
||||
}
|
||||
static int rb_objspace_reachable_object_p(VALUE obj, VALUE root);
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
|
@ -9369,6 +9337,59 @@ 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 ------------------------
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue