1
0
Fork 0
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:
Nobuyoshi Nakada 2019-07-04 00:58:52 +09:00
parent 9f1d67a68f
commit d0cd0866d8
No known key found for this signature in database
GPG key ID: 4BC7D6DF58D8DF60

87
gc.c
View file

@ -2954,39 +2954,7 @@ should_be_finalizable(VALUE obj)
rb_check_frozen(obj); rb_check_frozen(obj);
} }
struct reachable_object_data { static int rb_objspace_reachable_object_p(VALUE obj, VALUE root);
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;
}
/* /*
* call-seq: * call-seq:
@ -9369,6 +9337,59 @@ rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE,
POP_MARK_FUNC_DATA(); 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 ------------------------ ------------------------ Extended allocator ------------------------
*/ */