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