[PATCH] malloc: Run fork handler as late as possible [BZ #19431]

Florian Weimer fweimer@redhat.com
Tue Apr 12 19:15:00 GMT 2016


On 04/12/2016 08:16 PM, Torvald Riegel wrote:
> On Thu, 2016-02-18 at 17:15 +0100, Florian Weimer wrote:
>> On 02/15/2016 07:10 PM, Torvald Riegel wrote:
>>
>>>> It explicitly encodes the lock order in the implementations of fork,
>>>> and does not rely on the registration order, thus avoiding the deadlock.
>>>>
>>>> I couldn't test the Hurd bits, but the changes look straightforward enough.
>>>
>>> Are those changes, and thus the new scheme, documented anywhere?
>>
>> Fork handlers used by the implementation should be invisible to
>> applications.  The old one wasn't, and this was a bug.
>
> But have you documented this and your understanding of the
> synchronization scheme anywhere?  Your explanation in the email with the
> patch seems more detailed than the comments in the code.

That's because I'm talking mainly about removed code and explaining a 
bug.  I'm not sure how this information will be useful to future 
developers once the bug is gone.  We have a regression test, which 
should avoid reintroducing precisely the same bug.  For similar issues, 
we need to rely on code review and collective memory.

>>> I think it's really worthwhile to always update and improve the
>>> documentation, especially if we're kind of (re)discovering knowledge
>>> about the current implementation such as in this case.  I know this is
>>> extra work, but if this isn't documented, it's less likely anybody but
>>> you will be aware of how this all works.
>>
>> Do you mean something like this inside the fork implementation?
>>
>>    /* Acquire malloc locks.  This needs to come last because fork
>>       handlers may use malloc, and the libio list lock has an indirect
>>       malloc dependency as well (via the getdelim function).  */
>>    __malloc_fork_lock_parent ();
>
> Not quite.  IIRC this is one comment in one part of the code, but it's
> not easy to find it from the other parts of code that are related.
>
> One of the main motivations to document the synchronization scheme is to
> avoid requiring future developers that want to modify the code to
> closely review all the code (eg, to look for comments such as the one
> above).

The cycle isn't there anymore, so it would not particularly helpful to 
mention fork handlers in a comment on _IO_flush_all_lockp.

I would even go one step further: It would be misleading because it 
implies that we are confident about the libio locking behavior and lack 
of cycles.  But libio calls user-supplied callbacks (set by fopencookie) 
while implementation locks are acquired (again in _IO_flush_all_lockp). 
  Diagnostic functions in the malloc subsystem call into libio (via 
stdio streams) while malloc locks are acquired, and libio may in turn 
use malloc.  I'm sure I can find more examples with more poking.

> (The thinking is that, simplified, in sequential code it's
> sufficient to look at the callers or the contract of your function,
> whereas in concurrent code you don't easily know who is actually
> affected by a particiular lock acquisition order.)

With callbacks, you can't be sure even with sequential code.

> This is made easier if there's an overview of the synchronization
> somewhere in the code, and it is referenced in affected parts of the
> code.

I can add some comments to libio with what I have found, but this 
doesn't really related to the locking cycle I removed (because again, 
it's no longer there).

>>>> diff --git a/malloc/malloc-private.h b/malloc/malloc-private.h
>>>> new file mode 100644
>>>> index 0000000..2fef840
>>>> --- /dev/null
>>>> +++ b/malloc/malloc-private.h
>>>
>>> Should this perhaps be malloc-internal.h to match libc-internal.h?
>>
>> We also have libio/libioP.h, and include/malloc.h.  But I think a
>> separate header makes sense if its contents is truly internal.
>>
>> What are the preferences here?
>
> I think having an internal header is good, but I can't give a definitive
> reply regarding what the project prefers.

See my reply to Roland.  I was under the impression you objected to the 
name.

Florian



More information about the Libc-alpha mailing list