38 */
39 status = pthread_mutex_unlock (&mutex);
40 if (status != 0)
41 err_abort (status, 'Unlock in parent handler');
42 }
43
44 /*
45 * This routine will be called after executing the fork, within
46 * the child process.
47 */
48 void fork_child (void)
49 {
50 int status; 51
52 /*
53 * Update the file scope 'self_pid' within the child process, and
54 * unlock the mutex.
55 */
56 self_pid = getpid ();
57 status = pthread_mutex_unlock (&mutex);
58 if (status != 0)
59 err_abort (status, 'Unlock in child handler');
60 }
61
62 /*
63 * Thread start routine, which will fork a new child process.
64 */
65 void *thread_routine (void *arg)
66 {
67 pid_t child_pid;
68 int status;
69
70 child_pid = fork ( );
71 if (child_pid == (pid_t)-l)
72 errno_abort ('Fork');
73
74 /*
75 * Lock the mutex — without the atfork handlers, the mutex will
76 * remain locked in the child process and this lock attempt will
77 * hang (or fail with EDEADLK) in the child.
78 */
79 status = pthread_mutex_lock (&mutex);
80 if (status != 0)
81 err_abort (status, 'Lock in child');
82 status = pthread_mutex_unlock (&mutex);
83 if (status != 0)
84 err_abort (status, 'Unlock in child');
85 printf ('After fork: %d (%d)
', child_pid, self_pid);
86 if (child_pid != 0) {
87 if ((pid_t)-l == waitpid (child_pid, (int*)0, 0))
88 errno_abort ('Wait for child');
89 }
90 return NULL;
91 }
92
93 int main (int argc, char *argv[])
94 {
95 pthread_t fork_thread;
96 int atfork_flag = 1;
97 int status;
98
99 if (argc > 1)
100 atfork_flag = atoi (argv[l]);
101 if (atfork_flag) {
102 status = pthread_atfork (
103 fork_prepare, fork_parent, fork_child);
104 if (status != 0)
105 err_abort (status, 'Register fork handlers');
106 }
107 self_pid = getpid ();
108 status = pthread_mutex_lock (&mutex);
109 if (status != 0)
110 err_abort (status, 'Lock mutex');
111 /*
112 * Create a thread while the mutex is locked. It will fork a
113 * process, which (without atfork handlers) will run with the
114 * mutex locked.
115 */
116 status = pthread_create (
117 &fork_thread, NULL, thread_routine, NULL);
118 if (status != 0)
119 err_abort (status, 'Create thread');
120 sleep (5);
121 status = pthread_mutex_unlock (&mutex);
122 if (status != 0)
123 err_abort (status, 'Unlock mutex');
124 status = pthread_join (fork_thread, NULL);
125 if (status != 0)
126 err_abort (status, 'Join thread');
127 return 0;
128 }
¦ atfork.c
Now, imagine you are writing a library that manages network server connections, and you create a thread for each network connection that listens for service requests. In your