diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2023-04-25 08:37:05 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2023-04-28 21:17:43 +0300 |
commit | 0de4e1bdbc7fc5ca2f78864607e06a41b48bd466 (patch) | |
tree | ee36bda53acaa9d64e4c4eded9797e200a2d1ba5 | |
parent | 74f06fe0606c300b9e61267f77118ea6817b520d (diff) | |
download | bdwgc-0de4e1bdbc7fc5ca2f78864607e06a41b48bd466.tar.gz |
Fix infinite loop in disable_gc_for_dlopen and GC_wait_for_gc_completion
(a cherry-pick of commit 2dff48cb3 from 'release-8_2')
Issue #257 (bdwgc).
* alloc.c (GC_collect_a_little_inner): Call GC_mark_some() (in a loop)
even if GC_dont_gc.
* alloc.c (GC_collect_a_little, GC_allocobj): Do not call
GC_collect_a_little_inner() if GC_dont_gc.
* tests/test.c (check_heap_stats): Do not call GC_collect_a_little()
(repeatedly) if GC_is_disabled().
-rw-r--r-- | alloc.c | 14 | ||||
-rw-r--r-- | tests/test.c | 3 |
2 files changed, 10 insertions, 7 deletions
@@ -621,8 +621,6 @@ GC_INNER void GC_collect_a_little_inner(int n) IF_CANCEL(int cancel_state;) GC_ASSERT(I_HOLD_LOCK()); - if (GC_dont_gc) return; - DISABLE_CANCEL(cancel_state); if (GC_incremental && GC_collection_in_progress()) { int i; @@ -630,6 +628,7 @@ GC_INNER void GC_collect_a_little_inner(int n) for (i = GC_deficit; i < max_deficit; i++) { if (GC_mark_some((ptr_t)0)) { + if (GC_dont_gc) break; /* Need to finish a collection */ # ifdef SAVE_CALL_CHAIN GC_save_callers(GC_last_stack); @@ -661,7 +660,7 @@ GC_INNER void GC_collect_a_little_inner(int n) if (GC_deficit < 0) GC_deficit = 0; } - } else { + } else if (!GC_dont_gc) { GC_maybe_gc(); } RESTORE_CANCEL(cancel_state); @@ -676,7 +675,9 @@ GC_API int GC_CALL GC_collect_a_little(void) DCL_LOCK_STATE; LOCK(); - GC_collect_a_little_inner(1); + if (!GC_dont_gc) { + GC_collect_a_little_inner(1); + } result = (int)GC_collection_in_progress(); UNLOCK(); if (!result && GC_debugging_started) GC_print_all_smashed(); @@ -1521,7 +1522,8 @@ GC_INNER ptr_t GC_allocobj(size_t gran, int kind) while (*flh == 0) { ENTER_GC(); # ifndef GC_DISABLE_INCREMENTAL - if (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED) { + if (GC_incremental && GC_time_limit != GC_TIME_UNLIMITED + && !GC_dont_gc) { /* True incremental mode, not just generational. */ /* Do our share of marking work. */ GC_collect_a_little_inner(1); @@ -1538,7 +1540,7 @@ GC_INNER ptr_t GC_allocobj(size_t gran, int kind) if (*flh == 0) { ENTER_GC(); if (GC_incremental && GC_time_limit == GC_TIME_UNLIMITED - && !tried_minor) { + && !tried_minor && !GC_dont_gc) { GC_collect_a_little_inner(1); tried_minor = TRUE; } else { diff --git a/tests/test.c b/tests/test.c index 0db0ac02..f5ed27ab 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1710,7 +1710,8 @@ void check_heap_stats(void) # endif /* Garbage collect repeatedly so that all inaccessible objects */ /* can be finalized. */ - while (GC_collect_a_little()) { } + if (!GC_is_disabled()) + while (GC_collect_a_little()) { } for (i = 0; i < 16; i++) { GC_gcollect(); # ifndef GC_NO_FINALIZATION |