fix leak in abandoned block visiting

This commit is contained in:
daanx 2024-06-02 10:43:41 -07:00
parent f7fe5bf20e
commit 635d626c82
2 changed files with 18 additions and 5 deletions

View File

@ -946,7 +946,9 @@ static bool mi_arena_visit_abandoned_blocks(mi_subproc_t* subproc, int heap_tag,
_mi_arena_field_cursor_init(NULL, subproc, &current);
mi_segment_t* segment;
while ((segment = _mi_arena_segment_clear_abandoned_next(&current, true /* visit all */)) != NULL) {
if (!_mi_segment_visit_blocks(segment, heap_tag, visit_blocks, visitor, arg)) return false;
bool ok = _mi_segment_visit_blocks(segment, heap_tag, visit_blocks, visitor, arg);
_mi_arena_segment_mark_abandoned(segment);
if (!ok) return false;
}
return true;
}

View File

@ -39,6 +39,10 @@ static int ITER = 50; // N full iterations destructing and re-creating a
#define STRESS // undefine for leak test
#ifndef NDEBUG
#define HEAP_WALK // walk the heap objects?
#endif
static bool allow_large_objects = true; // allow very large objects? (set to `true` if SCALE>100)
static size_t use_one_size = 0; // use single object size of `N * sizeof(uintptr_t)`?
@ -129,7 +133,7 @@ static void free_items(void* p) {
custom_free(p);
}
/*
#ifdef HEAP_WALK
static bool visit_blocks(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg) {
(void)(heap); (void)(area);
size_t* total = (size_t*)arg;
@ -138,7 +142,7 @@ static bool visit_blocks(const mi_heap_t* heap, const mi_heap_area_t* area, void
}
return true;
}
*/
#endif
static void stress(intptr_t tid) {
//bench_start_thread();
@ -183,9 +187,12 @@ static void stress(intptr_t tid) {
data[data_idx] = q;
}
}
#ifdef HEAP_WALK
// walk the heap
// size_t total = 0;
// mi_heap_visit_blocks(mi_heap_get_default(), true, visit_blocks, &total);
size_t total = 0;
mi_heap_visit_blocks(mi_heap_get_default(), true, visit_blocks, &total);
#endif
// free everything that is left
for (size_t i = 0; i < retain_top; i++) {
@ -205,6 +212,10 @@ static void test_stress(void) {
uintptr_t r = rand();
for (int n = 0; n < ITER; n++) {
run_os_threads(THREADS, &stress);
#ifdef HEAP_WALK
size_t total = 0;
mi_abandoned_visit_blocks(mi_subproc_main(), -1, true, visit_blocks, &total);
#endif
for (int i = 0; i < TRANSFERS; i++) {
if (chance(50, &r) || n + 1 == ITER) { // free all on last run, otherwise free half of the transfers
void* p = atomic_exchange_ptr(&transfer[i], NULL);