Fix potential bug with recursing too many times duing gc
This commit is contained in:
@ -658,19 +658,20 @@ static ptrdiff_t check_gc_root(RefcountContext *ctx, RefcountList **root_ptr) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
uintptr_t count;
|
uintptr_t count;
|
||||||
|
queue = refcount_list_pop_full(queue, NULL, &ctx->alloc);
|
||||||
if (ht_has(counts, obj)) {
|
if (ht_has(counts, obj)) {
|
||||||
count = HT_UUNSTUFF(ht_get(counts, obj));
|
count = HT_UUNSTUFF(ht_get(counts, obj));
|
||||||
} else {
|
} else {
|
||||||
count = REFCOUNT_OBJECT_ENTRY(ctx, obj)->impl.counted.ref_count;
|
count = REFCOUNT_OBJECT_ENTRY(ctx, obj)->impl.counted.ref_count;
|
||||||
++seen_objects;
|
++seen_objects;
|
||||||
|
// don't recuse into objects multiple times
|
||||||
|
obj_held_refs(ctx, obj, &queue);
|
||||||
}
|
}
|
||||||
queue = refcount_list_pop_full(queue, NULL, &ctx->alloc);
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
ht_insert(counts, obj, HT_STUFF(--count));
|
ht_insert(counts, obj, HT_STUFF(--count));
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
++clear_objects;
|
++clear_objects;
|
||||||
}
|
}
|
||||||
obj_held_refs(ctx, obj, &queue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptrdiff_t freed_count = 0;
|
ptrdiff_t freed_count = 0;
|
||||||
|
@ -144,6 +144,9 @@ int main(int argc, const char **argv) {
|
|||||||
assert(refcount_context_garbage_collect(c) == 0);
|
assert(refcount_context_garbage_collect(c) == 0);
|
||||||
assert(refcount_context_num_refs(c, a_with_destructor) == 1);
|
assert(refcount_context_num_refs(c, a_with_destructor) == 1);
|
||||||
assert(refcount_context_remove_destructor(c, a_with_destructor, &key));
|
assert(refcount_context_remove_destructor(c, a_with_destructor, &key));
|
||||||
|
assert(refcount_context_ref(c, a_with_destructor));
|
||||||
|
assert(refcount_context_garbage_collect(c) == 0);
|
||||||
|
assert(refcount_context_unref(c, a_with_destructor));
|
||||||
assert(!refcount_context_is_doing_gc(c));
|
assert(!refcount_context_is_doing_gc(c));
|
||||||
ctx_and_flag.should_be_doing_gc = true;
|
ctx_and_flag.should_be_doing_gc = true;
|
||||||
assert(refcount_context_garbage_collect(c) == 26);
|
assert(refcount_context_garbage_collect(c) == 26);
|
||||||
|
Reference in New Issue
Block a user