From 6cfc8ad9d054b0541a24a73e2fa885ca166f6be6 Mon Sep 17 00:00:00 2001 From: Daan Date: Fri, 6 Jun 2025 21:29:33 -0700 Subject: [PATCH] improve handling of commit failure in arena allocation --- src/arena.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/arena.c b/src/arena.c index e46ad626..61903c5d 100644 --- a/src/arena.c +++ b/src/arena.c @@ -200,20 +200,21 @@ static mi_decl_noinline void* mi_arena_try_alloc_at( // now actually commit bool commit_zero = false; if (!mi_arena_commit(arena, p, mi_size_of_slices(slice_count), &commit_zero, mi_size_of_slices(slice_count - already_committed_count))) { - memid->initially_committed = false; + // if the commit fails, we roll back + _mi_arenas_free( p, mi_size_of_slices(slice_count), *memid); // this will uncommit as well + return NULL; } - else { - // committed - if (commit_zero) { memid->initially_zero = true; } - #if MI_DEBUG > 1 - if (memid->initially_zero) { - if (!mi_mem_is_zero(p, mi_size_of_slices(slice_count))) { - _mi_error_message(EFAULT, "interal error: arena allocation was not zero-initialized!\n"); - memid->initially_zero = false; - } + + // committed + if (commit_zero) { memid->initially_zero = true; } + #if MI_DEBUG > 1 + if (memid->initially_zero) { + if (!mi_mem_is_zero(p, mi_size_of_slices(slice_count))) { + _mi_error_message(EFAULT, "interal error: arena allocation was not zero-initialized!\n"); + memid->initially_zero = false; } - #endif } + #endif } else { // already fully committed. @@ -233,8 +234,7 @@ static mi_decl_noinline void* mi_arena_try_alloc_at( } } else { - // no need to commit, but check if already fully committed - // commit requested, but the range may not be committed as a whole: ensure it is committed now + // no need to commit, but check if it is already fully committed memid->initially_committed = mi_bitmap_is_setN(arena->slices_committed, slice_index, slice_count); if (!memid->initially_committed) { // partly committed.. adjust stats @@ -247,6 +247,7 @@ static mi_decl_noinline void* mi_arena_try_alloc_at( mi_assert_internal(mi_bbitmap_is_clearN(arena->slices_free, slice_index, slice_count)); if (commit) { mi_assert_internal(mi_bitmap_is_setN(arena->slices_committed, slice_index, slice_count)); } + if (commit) { mi_assert_internal(memid->initially_committed); } mi_assert_internal(mi_bitmap_is_setN(arena->slices_dirty, slice_index, slice_count)); return p;