See pthread_atfork , especially the JUSTIFICATION section, for a discussion of fork issues in a multi-threaded environment. It also gives a hint about what should be valid before and after fork inside the child and parent.
UPDATE: the Rationale section is non-normative, and it is in conflict with other parts of the standard. For more information, see this Dave Butenhof Defect Report.
Immediate exec after fork should be safe for any state of a multi-threaded program (i.e. any threads containing any mutexes). As for things between fork and exec , the situation is complicated:
Most importantly, only one thread (the one called fork ) is duplicated in the child process. Therefore, any mutex held by another thread at the time of fork is blocked forever. That is, (provided that the mutexes are not related to the process), its copy in the child process is locked forever, because there is no thread to unlock it.
Disabling the mutex after fork is safe when possible, that is, if the fork ing thread belongs to the mutex in the first place. As pthread_atfork handlers usually work: locking mutexes to fork , unlocking in the child device, and unlocking in the parent.
How to get the mutex belonging to the process before fork (remember, we are discussing a copy in the child address space): if it belonged to the fork ing stream, it is recursive blocking (works for PTHREAD_MUTEX_RECURSIVE ); if it belonged to another thread, it remains blocked forever and cannot be re-acquired.
By registering the appropriate pthread_atfork handlers, third-party libraries can guarantee the security of use between fork and exec . (I would expect that this is mainly from runtime of programming languages, and not for general purpose libraries).
After some further research, I would recommend not relying on pthread_atfork and not doing anything except asynchronous signal calls between fork and exec (giving up fork / exec for posix_spawn would be even better).
The problem is that fork itself can be called in the signal handler. This excludes any non-trivial use of pthread_atfork , even if its JUSTIFICATION explicitly mentions unlocking mutexes and re-creating threads (!) In the child process.
I think the βgray areaβ of the various possible interpretations remains:
- For
pthread_atfork handlers in a program that is known to never call fork in a signal handler. - For actions other than pthread-atfork that occur around a
fork call that is not in the signal handler.
But it is crystal clear which reading should be used for portable applications.