LWN.net Logo

I think it's pretty clear, actually...

I think it's pretty clear, actually...

Posted Nov 2, 2011 21:49 UTC (Wed) by quotemstr (subscriber, #45331)
In reply to: I think it's pretty clear, actually... by khim
Parent article: libabc: a demonstration library for kernel developers

> half of it is dedicated to the detailed explanation for why pthread_atfork should never be used.

No it isn't. Did you read the linked manpage? Its lengthy rationale section explains why one *would* want to use pthread_atfork, and why a bare fork (i.e. *not* using pthread_atfork) is discouraged.

Also, most of these criticisms don't apply for fork-exec: who cares whether a mutex is held in a child when all that child will ever do is exec?


(Log in to post comments)

I think it's pretty clear, actually...

Posted Nov 2, 2011 22:33 UTC (Wed) by gus3 (guest, #61103) [Link]

The pthread_atfork() page (check the link I provide in my earlier comment) does list in the "Rationale" section several reasons why using the function is a dicey proposition.

I think it's pretty clear, actually...

Posted Nov 3, 2011 3:54 UTC (Thu) by RCL (guest, #63264) [Link]

> does list in the "Rationale" section several reasons why using the function is a dicey proposition

Where exactly?

It describes problems with fork() and "solution" of using fork() then exec().

Then it proceeds to describe pthread_atfork() as a means to resolve the problem.

Then it describes an example usage of pthread_atfork().

In the last two lines it describes the order of registering atfork() handlers.

*Nowhere* in the document it warns against using pthread_atfork() nor acknowledges its 'brokenness'.

I think it's pretty clear, actually...

Posted Nov 6, 2011 22:18 UTC (Sun) by foom (subscriber, #14868) [Link]

Well, in my experience (writing private software), every time someone has wanted to use pthread_atfork, I've recommended that they not. For one very simple reason: it does not distinguish between the common activity of spawning a process (fork/exec) and the relatively rare activity of forking and keeping both halves.

So, for example, you might shutdown some auxiliary threads in a pthread_atfork prefork handler, to ensure that the threads aren't in the middle of corrupting your library's state when the child process wants to call into your library. But, that's entirely unnecessary work if the next action was going to be exec! It just causes fork/exec to be slower, for no good reason.

Instead, we use an explicit teardown function that you can call if you like, before non-exec forks.

Actually fork does THAT for you...

Posted Nov 7, 2011 17:32 UTC (Mon) by khim (subscriber, #9252) [Link]

So, for example, you might shutdown some auxiliary threads in a pthread_atfork prefork handler, to ensure that the threads aren't in the middle of corrupting your library's state when the child process wants to call into your library.

You don't need to do that. After fork just one thread survives. But you do need to either restart "zombie" threads or free fresources assigned to them. And to do that correctly different libraries must cooperate - and it's not clear "how". If the whole machinery described in pthread_atfork does not look like something designed to give you countless problems then I'm not sure you must write libraries at all.

Actually fork does THAT for you...

Posted Nov 15, 2011 3:39 UTC (Tue) by foom (subscriber, #14868) [Link]

> You don't need to do that. After fork just one thread survives.

Sure, but cleaning up after whatever the other thread was doing at the instant of the fork is generally impossible. You either need to grab a lock (or similar) in your atfork prefork handler to force the other thread into a known quiescent state, or shut it down. But, you probably don't really want to do either one before a fork-exec, it's just a waste of time.

> If the whole machinery described in pthread_atfork does not look like something designed to give you countless problems then I'm not sure you must write libraries at all.

I think the only thing pthread_atfork is *really* useful for is to ensure that libc's malloc() will keep working after fork().

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds