PreviousNext

Forking in a Threaded Application

The fork( ) system call causes the creation of an exact clone of the caller's address space, resulting in the execution by two address spaces of the same code. In order to avoid the problems that would arise in a threaded environment when one thread, possibly without the others' knowledge, executes a fork( ), the POSIX model defines fork( ) to result in the propagation of the calling thread only. Any other active threads are immediately terminated without notice.

The abrupt destruction of the other threads means that any mutexes they may have been holding at the time of the fork( ) will persist in the locked (and therefore unacquirable) state. On the other hand, assuming that the call to fork( ) is followed by a call to exec( ), then the outstanding mutexes will remain so only until exec( ) is called, when the new process space will be reinitialized.

Thus, out-of-state mutexes are a problem for the forked thread only in the interval between the fork( ) and the exec( ). Even so, as long as no calls occur here to routines outside the application, you can determine whether the thread is going to encounter any mutexes that could have been locked by the destroyed threads. However, it is impossible to be sure of this if calls into other libraries, which may have hidden interdependencies, occur in this interval.

Aside from these considerations, there is also the question of what happens when exec( ) fails and execution returns to the original forking (and now lone) thread, which is left with an address space that may contain out-of-state mutexes (as well as an inconsistent state in the data protected by the mutexes) as a result of the fork( ).

DCE does not support the "simple" fork( ); it supports only the fork( ) and exec( ) sequence. For cases where forking in the presence of threads is felt to be necessary, DCE threads provides a mechanism, the atfork( ) call, which allows you to install "fork handler" routines for an application or a library. These routines will be automatically run as follows:

· A routine that will be run just prior to the fork in the parent process; that is, just before all of the other threads are terminated

· A routine that will be run in the child process just after the fork occurs; that is, just after all the other threads are terminated

· A routine that will be run in the parent process just after the fork occurs; that is, just before the parent (forking) thread resumes execution