|
The wait function blocks the calling process until one of the child processes exits (or an error occurs). It returns a status code via an integer pointer argument, from which you can extract information about how the child process exited. For instance, the WEXITSTATUS macro extracts the child process’s exit code.
You can use the WIFEXITED macro to determine from a child process’s exit status whether that process exited normally (via the exit function or returning from main) or died from an unhandled signal. In the latter case, use the WTERMSIG macro to extract from its exit status the signal number by which it died.
The waitpid function can be used to wait for a specific child process to exit instead of any child process. The wait3 function returns CPU usage statistics about the exiting child process, and the wait4 function allows you to specify additional options about which processes to wait for.
Zombie Processes
If a child process terminates while its parent is calling a wait function, the child process vanishes and its termination status is passed to its parent via the wait call. But when a child process terminates while the parent is not calling wait, it becomes a Zombie Process.
A zombie process is a process that has terminated but had not been cleaned up yet. It is the responsibility of the parent process to clean up its zombie children. The wait functions do this, too, so it is not necessary to track whether your child process is still executing before waiting for it. Suppose, for instance, that a program forks a child process, performs some other computations, and then calls wait. If the child process had not terminated at that point, the parent process will block in the wait call until the child process finishes. If the child process finishes before the parent process calls wait, the child process becomes a Zombie. When the parent process calls wait, the zombie child’s termination status is extracted, the child process is deleted, and the wait call returns immediately. If the parent does not clean up its children, they stay around in the system, as Zombie processes.
Cleaning up children asynchronously
If you are using a child process simply to exec another program, it is fine to call wait immediately in the parent process, which will block until the child process completes. But often you will want the parent process to continue running, as one or more children execute synchronously. In order to be sure that you clean up child processes that have completed so that you don’t leave zombie processes, mainly two suggestive approaches can be used.
One approach would be for the parent process to call wait3 or wait4 periodically, to clean up zombie children. Calling wait for this purpose doesn’t work well because if no children had terminated, the call will block until one closes. However wait3 and wait4 take an additional flag parameter, to which you can pass the flag value WNOHANG. With this flag, the function runs in non-blocking mode- it will clean up a terminated child process if there is one, or simply return if there isn’t.
A more elegant solution is to notify the parent process when a child terminates. Fortunately linux does this for the users, using signals. When a child process terminates, linux sends the parent process the SIGCHLD signal.
Thus an easy way to clean up child processes is by handling SIGCHLD of course, when cleaning up the child process, it is important to store its termination status if this information is needed, because once the process is cleaned up using wait, that information is no longer available.
|