[PATCH] posix: Avoid allocation while holding atfork_lock [BZ 34321]
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Mon Jun 29 11:14:23 GMT 2026
On 26/06/26 19:59, H.J. Lu wrote:
> On Sat, Jun 27, 2026 at 1:31 AM Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>>
>> __register_atfork inserted the new handler into a dynamic array while
>> holding atfork_lock, and growing that array calls the public/iterposable
>> malloc. An allocator replacement whose own lock is also taken from a
>> registered pthread_atfork prepare handler can therefore deadlock:
>>
>> Thread A: fork Thread B: __register_atfork
>> ------------------------------------- -----------------------------------
>> :139 unlock(atfork_lock)
>> :141 prepare() -> lock(L) [holds L]
>> :39 lock(atfork_lock) [holds atfork]
>> :44 emplace -> malloc -> lock(L)
>> BLOCKS on L (held by A)
>> :144 lock(atfork_lock)
>> BLOCKS on atfork (held by B)
>> => DEADLOCK (A: holds L, waits atfork; B: holds atfork, waits L)
>>
>> Replace the dynamic array with a doubly linked list (include/list.h).
>> A new node is allocated outside atfork_lock and only linked in while the
>> lock is held. __unregister_atfork moves nodes to a free pool instead of
>> freeing them, and __register_atfork reuses a pooled node when one is
>> available, so neither path allocates or frees under atfork_lock in the
>> steady state; malloc runs only to grow the pool, always outside the lock.
>> This preserves the current allocation guarantee of the dynarray.
>>
>> Checked on x86_64-linux-gnu and aarch64-linux-gnu.
>
> Is it possible to create a run-time test with an alternate malloc via
> LD_PRELOAD on systems where alternate malloc is available
> similar to
>
> https://gitlab.com/x86-glibc/glibc/-/commits/users/hjl/test/malloc
I think for checking this issue being a LD_PRELOAD or malloc implemented
in the binary itself does not really matter. The mechanism glibc will used
to trigger is the same, and being on the binary makes it simpler.
More information about the Libc-alpha
mailing list