Solutions to Selected Exercises 1431
orphaned, the grandchild is adopted by init (process ID of 1). The program doesn’t
need to perform a second wait() call, since init automatically reaps the zombie
when the grandchild terminates. Therein lies a possible use for this code sequence:
if we need to create a child for which we can’t later wait, then this sequence can be
used to ensure that no zombie results. One example of such a requirement is where
the parent execs some program that is not guaranteed to perform a wait (and we
don’t want to rely on setting the disposition of SIGCHLD to SIG_IGN, since the
disposition of an ignored SIGCHLD after an exec() is left unspecified by SUSv3).
27-5. The string given to printf() doesn’t include a newline character, and therefore the
output is not flushed before the execlp() call. The execlp() overwrites the existing
program’s data segments (as well as the heap and stack), which contain the stdio
buffers, and thus the unflushed output is lost.
27-6. SIGCHLD is delivered to the parent. If the SIGCHLD handler attempts to do a wait(), then
the call returns an error (ECHILD) indicating that there were no children whose status
could be returned. (This assumes that the parent had no other terminated
children. If it did, then the wait() would block; or if waitpid() was used with the
WNOHANG flag, waitpid() would return 0.) This is exactly the situation that may arise if a
program establishes a handler for SIGCHLD before calling system().
Chapter 29
29-1. There are two possible outcomes (both permitted by SUSv3): the thread deadlocks,
blocked while trying to join with itself, or the pthread_join() call fails, returning the
error EDEADLK. On Linux, the latter behavior occurs. Given a thread ID in tid, we can
prevent such an eventuality using the following code:
if (!pthread_equal(tid, pthread_self()))
pthread_join(tid, NULL);
29-2. After the main thread terminates, threadFunc() will continue working with storage
on the main thread’s stack, with unpredictable results.
Chapter 31
31-1. A solution is provided in the file threads/one_time_init.c in the source code
distribution for this book.
Chapter 33
33-2. The SIGCHLD signal that is generated on child termination is process-directed. It may
be delivered to any thread (not necessarily the one that called fork()) that is not
blocking the signal.
Chapter 34
34-1. Suppose that the program is part of a shell pipeline:
$ ./ourprog | grep 'some string'