pthread_atfork - register fork handlers
int pthread_atfork(void (*prepare)(void),void (*parent)(void),
The pthread_atfork()function shall declare fork handlers to be called before and after fork(),in the context of the thread that called fork().The prepare fork handler shall be called before fork()processing commences. The parent fork handle shall be called after fork()processing completes in the parent process. The child fork handler shallbe called after fork()processing completes in the child process. If no handling is desired at one ormore of these three points, the corresponding fork handler address(es) may beset to NULL.
The order ofcalls to pthread_atfork() is significant. The parentand child fork handlers shall be called in the order in which they wereestablished by calls to pthread_atfork(). The prepare forkhandlers shall be called in the opposite order.
Upon successful completion, pthread_atfork()shall return a value of zero; otherwise, an error number shall be returned toindicate the error.
The pthread_atfork() function shallfail if:
[ENOMEM] -- Insufficient table space existsto record the fork handler addresses.
The pthread_atfork() function shallnot return an error code of [EINTR].
There are at least two serious problemswith the semantics of fork()in a multi-threaded program. One problem has to do with state (for example,memory) covered by mutexes. Consider the case where one thread has a mutexlocked and the state covered by that mutex is inconsistent while another threadcalls fork().In the child, the mutex is in the locked state (locked by a nonexistent threadand thus can never be unlocked). Having the child simply reinitialize the mutexis unsatisfactory since this approach does not resolve the question about howto correct or otherwise deal with the inconsistent state in the child.
It is suggested thatprograms that use fork()call an execfunction very soon afterwards in the child process, thus resetting all states.In the meantime, only a short list of async-signal-safe library routines arepromised to be available.
Unfortunately, this solution does notaddress the needs of multi-threaded libraries. Application programs may not beaware that a multi-threaded library is in use, and they feel free to call anynumber of library routines between the fork()and execcalls, just as they always have. Indeed, they may be extant single-threadedprograms and cannot, therefore, be expected to obey new restrictions imposed bythe threads library.
On the other hand, the multi-threadedlibrary needs a way to protect its internal state during fork()in case it is re-entered later in the child process. The problem arisesespecially in multi-threaded I/O libraries, which are almost sure to be invokedbetween the fork()and execcalls to effect I/O redirection. The solution may require locking mutexvariables during fork(),or it may entail simply resetting the state in the child after the fork()processing completes.
The pthread_atfork()function provides multi-threaded libraries with a means to protect themselvesfrom innocent application programs that call fork(),and it provides multi-threaded application programs with a standard mechanismfor protecting themselves from fork()calls in a library routine or the application itself.
The expected usage is that the preparehandler acquires all mutex locks and the other two fork handlers release them.
For example, an application can supply a prepareroutine that acquires the necessary mutexes the library maintains and supply childand parent routines that release those mutexes, thus ensuring that thechild gets a consistent snapshot of the state of the library (and that nomutexes are left stranded). Alternatively, some libraries might be able tosupply just a child routine that reinitializes the mutexes in thelibrary and all associated states to some known value (for example, what it waswhen the image was originally executed).
A higher-level package may acquire locks onits own data structures before invoking lower-level packages. Under thisscenario, the order specified for fork handler calls allows a simple rule ofinitialization for avoiding package deadlock: a packageinitializes all packages on which it depends before it calls the pthread_atfork()function for itself.
1. It issuggested that in a multi-threaded program. programs that use fork()call an execfunction very soon afterwards in the child process, thus resetting all states.In the meantime, only a short list of async-signal-safe library routines arepromised to be available.
2. The expected usage is thatthe prepare handler acquires all mutex locks and the other two forkhandlers release them.
3. Pay attentionon the order of calls to pthread_atfork() to make sure the low-levelpackage’s prepare handle is calledfirst.
4. Only a shortlist of async-signal-safe library routines are promised to be available for parentand child fork handler.malloc/free(new/delete?), printf and so on are not async-signal-safe!
5. In theory,1) only async-signal-safe can be called in parent and child fork handler; 2) many OS functions havestatic variable, whom status can’t clean up; pthread_atfork()function is still an option to reduce the bug of fork() in multi-threadprogram, especially for LIB.
6. If #4 isobey, some occasional bug can happen.