From 77cc3c45de7daaf7f3f70236b37f14734d4c69f4 Mon Sep 17 00:00:00 2001 From: Alexander Rosenberg Date: Tue, 9 Sep 2025 04:06:59 -0700 Subject: [PATCH] Fix potential bug with recursing too many times duing gc --- src/refcount.c | 5 +++-- test/test_refcount.c | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/refcount.c b/src/refcount.c index c04c592..841a163 100644 --- a/src/refcount.c +++ b/src/refcount.c @@ -658,19 +658,20 @@ static ptrdiff_t check_gc_root(RefcountContext *ctx, RefcountList **root_ptr) { continue; } uintptr_t count; + queue = refcount_list_pop_full(queue, NULL, &ctx->alloc); if (ht_has(counts, obj)) { count = HT_UUNSTUFF(ht_get(counts, obj)); } else { count = REFCOUNT_OBJECT_ENTRY(ctx, obj)->impl.counted.ref_count; ++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) { ht_insert(counts, obj, HT_STUFF(--count)); if (count == 0) { ++clear_objects; } - obj_held_refs(ctx, obj, &queue); } } ptrdiff_t freed_count = 0; diff --git a/test/test_refcount.c b/test/test_refcount.c index b6904f6..d27c383 100644 --- a/test/test_refcount.c +++ b/test/test_refcount.c @@ -144,6 +144,9 @@ int main(int argc, const char **argv) { assert(refcount_context_garbage_collect(c) == 0); assert(refcount_context_num_refs(c, a_with_destructor) == 1); 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)); ctx_and_flag.should_be_doing_gc = true; assert(refcount_context_garbage_collect(c) == 26);