Copyright (C) 2000-2012 |
GNU Info (libc.info)Threads and ForkThreads and Fork ================ It's not intuitively obvious what should happen when a multi-threaded POSIX process calls `fork'. Not only are the semantics tricky, but you may need to write code that does the right thing at fork time even if that code doesn't use the `fork' function. Moreover, you need to be aware of interaction between `fork' and some library features like `pthread_once' and stdio streams. When `fork' is called by one of the threads of a process, it creates a new process which is copy of the calling process. Effectively, in addition to copying certain system objects, the function takes a snapshot of the memory areas of the parent process, and creates identical areas in the child. To make matters more complicated, with threads it's possible for two or more threads to concurrently call fork to create two or more child processes. The child process has a copy of the address space of the parent, but it does not inherit any of its threads. Execution of the child process is carried out by a new thread which returns from `fork' function with a return value of zero; it is the only thread in the child process. Because threads are not inherited across fork, issues arise. At the time of the call to `fork', threads in the parent process other than the one calling `fork' may have been executing critical regions of code. As a result, the child process may get a copy of objects that are not in a well-defined state. This potential problem affects all components of the program. Any program component which will continue being used in a child process must correctly handle its state during `fork'. For this purpose, the POSIX interface provides the special function `pthread_atfork' for installing pointers to handler functions which are called from within `fork'. - Function: int pthread_atfork (void (*PREPARE)(void), void (*PARENT)(void), void (*CHILD)(void)) `pthread_atfork' registers handler functions to be called just before and just after a new process is created with `fork'. The PREPARE handler will be called from the parent process, just before the new process is created. The PARENT handler will be called from the parent process, just before `fork' returns. The CHILD handler will be called from the child process, just before `fork' returns. `pthread_atfork' returns 0 on success and a non-zero error code on error. One or more of the three handlers PREPARE, PARENT and CHILD can be given as `NULL', meaning that no handler needs to be called at the corresponding point. `pthread_atfork' can be called several times to install several sets of handlers. At `fork' time, the PREPARE handlers are called in LIFO order (last added with `pthread_atfork', first called before `fork'), while the PARENT and CHILD handlers are called in FIFO order (first added, first called). If there is insufficient memory available to register the handlers, `pthread_atfork' fails and returns `ENOMEM'. Otherwise it returns 0. The functions `fork' and `pthread_atfork' must not be regarded as reentrant from the context of the handlers. That is to say, if a `pthread_atfork' handler invoked from within `fork' calls `pthread_atfork' or `fork', the behavior is undefined. Registering a triplet of handlers is an atomic operation with respect to fork. If new handlers are registered at about the same time as a fork occurs, either all three handlers will be called, or none of them will be called. The handlers are inherited by the child process, and there is no way to remove them, short of using `exec' to load a new pocess image. To understand the purpose of `pthread_atfork', recall that `fork' duplicates the whole memory space, including mutexes in their current locking state, but only the calling thread: other threads are not running in the child process. Thus, if a mutex is locked by a thread other than the thread calling `fork', that mutex will remain locked forever in the child process, possibly blocking the execution of the child process. Or if some shared data, such as a linked list, was in the middle of being updated by a thread in the parent process, the child will get a copy of the incompletely updated data which it cannot use. To avoid this, install handlers with `pthread_atfork' as follows: have the PREPARE handler lock the mutexes (in locking order), and the PARENT handler unlock the mutexes. The CHILD handler should reset the mutexes using `pthread_mutex_init', as well as any other synchronization objects such as condition variables. Locking the global mutexes before the fork ensures that all other threads are locked out of the critical regions of code protected by those mutexes. Thus when `fork' takes a snapshot of the parent's address space, that snapshot will copy valid, stable data. Resetting the synchronization objects in the child process will ensure they are properly cleansed of any artifacts from the threading subsystem of the parent process. For example, a mutex may inherit a wait queue of threads waiting for the lock; this wait queue makes no sense in the child process. Initializing the mutex takes care of this. automatically generated by info2www version 1.2.2.9 |