Chapter 25. Process Termination

This chapter describes what happens when a process terminates. We begin by describing the use of exit() and _exit() to terminate a process. We then discuss the use of exit handlers to automatically perform cleanups when a process calls exit(). We conclude by considering some interactions between fork(), stdio buffers, and exit().

A process may terminate in two general ways. One of these is abnormal termination, caused by the delivery of a signal whose default action is to terminate the process (with or without a core dump), as described in Section 20.1. Alternatively, a process can terminate normally, using the _exit() system call.

#include <unistd.h>

void _exit(int status);

The status argument given to _exit() defines the termination status of the process, which is available to the parent of this process when it calls wait(). Although defined as an int, only the bottom 8 bits of status are actually made available to the parent. By convention, a termination status of 0 indicates that a process completed successfully, and a nonzero status value indicates that the process terminated unsuccessfully. There are no fixed rules about how nonzero status values are to be interpreted; different applications follow their own conventions, which should be described in their documentation. SUSv3 specifies two constants, EXIT_SUCCESS (0) and EXIT_FAILURE (1), that are used in most programs in this book.

A process is always successfully terminated by _exit() (i.e., _exit() never returns).

Programs generally don’t call _exit() directly, but instead call the exit() library function, which performs various actions before calling _exit().

#include <stdlib.h>

void exit(int status);

The following actions are performed by exit():

One other way in which a process may terminate is to return from main(), either explicitly, or implicitly, by falling off the end of the main() function. Performing an explicit return n is generally equivalent to calling exit(n), since the run-time function that invokes main() uses the return value from main() in a call to exit().

Performing a return without specifying a value, or falling off the end of the main() function, also results in the caller of main() invoking exit(), but with results that vary depending on the version of the C standard supported and the compilation options employed: