Wait System Call
A process can wait for one of its child processes to finish by executing the wait system call.

int wait(int  *status);

The value returned by wait is the process ID of the child process that terminated.
If the process that calls wait does not have any child processes, wait returns a value of -1 immediately.
If the process that calls wait has one or more child processes that has not yet terminated, then the calling process is suspended by the kernel until one of its child process terminates.
When a child process terminates and wait returns, if the  status argument is not NULL, the value passed to exit by the terminating child process is stored in the status variable.
Some additional info. is also returned by wait.

There are 3 conditions for which wait returns a process ID as its return value.
1. A child process called exit.
2. a child process was terminated by a signal.
3. A child process was being traced and the process stopped. This occurs when one process is tracing the execution of another process, such as when a debugger is being used to step through a process.

see fig. 2.6

Signal numbers are greater than zero, otherwise it would be impossible to distinguish between the three cases.
The core flag bit is one if the terminated process generated a core file, otherwise it is zero.

As mentioned previously, a process has a single parent process, but it can have many child processes. The following steps are done by the kernel when a process exits.

If the parent process of the exiting process has called the wait system call, the parent process is notified that a child process has terminated (i.e. the wait system call returns to the parent). The parent process is passed the child's exit status (the child's argument to the exit function), if the parent's status argument was nonzero.

If the parent process of the exiting process has called the wait system call, the parent process is notified that a child process has terminated (i.e. the wait system call returns to the parent).  The parent process is passed the child's exit status (the child's argument to the exit function), if the parent's status argument was nonzero.

If the parent process of the exiting process is not executing a wait, the terminating process is marked as a zombie process.  A zombie process is one that has terminated, but its parent has not waited for it yet.  The kernel releases all the resources being used by a zombie process (its memory, for e.g.) but has to at least maintain its exit status, until its parent waits for it.

The parent process ID of all the terminating process' child process is set to 1 (the init process).

If the process ID, process group ID, and terminal group ID fields of the terminating process are all equal, the hangup signal, SIGHUP, is sent to each process that has a process groupd ID equal to that of the terminating process.

What happens to the parent process ID of a child process when the parent process terminates beforre the child process? There are 2 possible scenarios to consider.

1. The child process terminates before the parent process. This is normal condition when we are entering commands to an interactive shell (assuming we don't logout before waiting for a command to complete).
a) If the parent process has already executed a wait, then the wait returns to the parent process with the process ID of the child that terminated.
b) If the parent process has not executed a wait, then the child process becomes a zombie process as mentioned above.

2. The parent process terminates before its child processes. This presents a problem, since the parent process IDs of any child processes are no longer valid, once the parent terminates.
The way Unix handles this is to find all processes (active or zombie) whose parent process ID equals the process ID of the terminating process.
For these child processes that are about to be orphaned, Unix sets their parent process ID to 1, the process ID of the init process. The init process, therefore, becomes the parent process of any orphaned processes.
The init process never terminates.  Other than having its parent process ID changed an executing child process is not aware that its parent process has terminated.

When a process exits, a SIGCLD signal is generated in the parent process. But by default, this signal is ignored.
Many programs are unaware of this signal.  The purpose of this signal is to allow the parent process to call wait to obtain the exit status of its child process.
If a process knows that it will spawn child processes, this is one technique to prevent its children from becoming zombies.
As mentioned earlier, if the parent does not wait for a child process that has terminated, that child becomes a zombie, until the parent also terminates. In some system (in most cases Unix system V) allows a process to prevent any of its child processes from becoming zombies. To do this, the parent has to execute

signal(SIGCLD, SIG_IGN);

to ignore this signal. This tells the kernel that the process is not interested in the exit status of its children. From this point on, the kernel will not generate zombie processes from the children of this process.