malloc: Use _int_free_chunk in tcache_thread_shutdown
Arjun Shankar
arjun@redhat.com
Wed Nov 19 12:30:16 GMT 2025
Hi Wilco,
> Directly call _int_free_chunk during tcache shutdown to avoid
> possible recursion.
While master has moved a bit since this was posted, it still applies
with a 3-way merge.
> Passes regress, OK for commit?
This line made it to the commit message.
I was looking to find the recursion path, and it looks like:
tcache_thread_shutdown -> libc_free -> tcache_double_free_verify -> libc_free.
Not really related to this change but tcache_double_free_verify seems
a little misleading since it doesn't just verify.
> diff --git a/malloc/malloc.c b/malloc/malloc.c
> index 6c02af5a271d21a40cfe199d118dd7e7ad886ed5..943d5afd821e78d3f5d702bdc6fdc5caf21262fb 100644
> --- a/malloc/malloc.c
> +++ b/malloc/malloc.c
> @@ -3346,6 +3346,7 @@ static void
> tcache_thread_shutdown (void)
> {
> int i;
> + mchunkptr p;
> tcache_perthread_struct *tcache_tmp = tcache;
>
> tcache_shutting_down = true;
> @@ -3367,11 +3368,14 @@ tcache_thread_shutdown (void)
> malloc_printerr ("tcache_thread_shutdown(): "
> "unaligned tcache chunk detected");
> tcache_tmp->entries[i] = REVEAL_PTR (e->next);
> - __libc_free (e);
> + e->key = 0;
> + p = mem2chunk (e);
> + _int_free_chunk (arena_for_chunk (p), p, chunksize (p), 0);
Looking at libc_free, what it does to blocks that eventually get put
into the tcache is:
1. tag memory back to libc ownership.
2. check for misalignment.
3. call tcache_double_free_verify to catch anything that was
previously freed into the tache, and is now being freed again.
So the second time round (while we are processing already tcached
blocks during this thread shutdown), we can skip these checks.
If I understand it correctly, doesn't this additional check that does
occur in libc_free before int_free_chunk now get skipped with this
change?:
/* Check size >= MINSIZE and p + size does not overflow. */
if (__glibc_unlikely (INT_ADD_OVERFLOW ((uintptr_t) p,
size - MINSIZE)))
return malloc_printerr_tail ("free(): invalid size");
> }
> }
>
> - __libc_free (tcache_tmp);
> + p = mem2chunk (tcache_tmp);
> + _int_free_chunk (arena_for_chunk (p), p, chunksize (p), 0);
> }
>
> /* Initialize tcache. In the rare case there isn't any memory available,
More information about the Libc-alpha
mailing list