[PATCH] posix: Avoid allocation while holding atfork_lock [BZ 34321]

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Tue Jun 30 13:38:59 GMT 2026



On 29/06/26 18:55, H.J. Lu wrote:
> On Mon, Jun 29, 2026 at 7:14 PM Adhemerval Zanella Netto
> <adhemerval.zanella@linaro.org> wrote:
>>
>>
>>
>> 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.
> 
> Without LD_PRELOAD, we can't be sure that the issue is really fixed.
> We may have fixed a slighly different issue.
I don't think this applies for the bug report, since what needs to be tested
is whether the process is using malloc interposition and if a pre-atfork
lock does not trigger a deadlock when multiple atfork handler are being
registered. It does not really matter if the malloc implementation is being 
provided by LD_PRELOAD or by the binary itself, the underlying mechanism if 
the same.

I can adapt to use LD_PRELOAD, it is just more boilerplate code though.


More information about the Libc-alpha mailing list