ptg10805159
Section 12.9 Threads andfork 459
- A child process is created.
- Thechildfork handler from module B is called to release all of module B’s locks
in the child process. - Thechildfork handler from module A is called to release all of module A’s locks
in the child process. - Theforkfunction returns to the child.
- Theparentfork handler from module B is called to release all of module B’s
locks in the parent process. - Theparentfork handler from module A is called to release all of module A’s
locks in the parent process. - Theforkfunction returns to the parent.
If the fork handlers serve to clean up the lock state, what cleans up the state of
condition variables? On some implementations, condition variables might not need any
cleaning up. However, an implementation that uses a lock as part of the
implementation of condition variables will requirecleaning up. The problem is that no
interface exists to allow us to do this. If the lock is embedded in the condition variable
data structure, then we can’t use condition variables after callingfork,because thereis
no portable way to clean up its state. On the other hand, if an implementation uses a
global lock to protect all condition variable data structures in a process, then the
implementation itself can clean up the lock in theforklibrary routine. Application
programs shouldn’t rely on implementation details like this, however.
Example
The program in Figure12.17 illustrates the use ofpthread_atforkand fork handlers.
#include "apue.h"
#include <pthread.h>
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
void
prepare(void)
{
int err;
printf("preparing locks...\n");
if ((err = pthread_mutex_lock(&lock1)) != 0)
err_cont(err, "can’t lock lock1 in prepare handler");
if ((err = pthread_mutex_lock(&lock2)) != 0)
err_cont(err, "can’t lock lock2 in prepare handler");
}
void
parent(void)
{