Often confusing two signals are SIGCLD and SIGCHLD, the signal SIGCLD originated from system V, the meaning of the signal and from the BSD signal sigchld inconsistent. The posix.1 signal is also known as SIGCHLD. The semantics of the signal sigchld from BSD are normal, and when the signal appears, the state of the child process changes, and then we need to call a wait function to see what happened.
System V has been different from other signals since the processing history of SIGCLD, Svr4i-based systems maintain this problematic tradition if we use function signal or sigset (the function used to set signal processing functions in SVR3) to set the processing function of the signal, SIGCLD early processing includes the following behaviors:
- If the signal processing function is specified as sig_ign, the child process of the calling process will never spawn a zombie process. Note This differs from the default processing of the signal and is ignored in Figure 10.1 when it refers to its default processing. Instead, when the child process terminates, the state of the child process is discarded, and if its parent process then calls one of the wait functions, the calling process is blocked until all the child processes are terminated, and then the wait function returns-1, and errno is set to Echild. (Note: The signal is ignored by default processing, but the default processing does not produce the above behavior, but we must set the processing function of the signal to sig_ign.)
POSIX.1 does not specify what happens when SIGCHLD is ignored, so the above processing is also allowed, and the XSI option requires that the processing be supported by the signal sigchld.
4.4BSD always generates a zombie process when SIGCHLD is ignored, and if we want to avoid a zombie process, we have to wait for all of the child processes, in SVR4, as long as the signal is called or one of the Sigset sets the SIGCHLD handler to Sig_ IGN, the zombie process will never be produced, and the 4 platforms described in this book are the same as the SVR4.
Using the function sigaction, we can set the SA_NOCLDWAIT flag to avoid the zombie process, which is supported for the 4 platforms described in this book.
- If we set SIGCLD's handler function, the kernel will immediately check if there is a child process waiting to be processed, and if so, call the SIGCLD function immediately.
The second of these changes the way we write the signal-processing functions, as we will in the following example.
Example
As mentioned in section 10.4, the first thing in the signal processing function is to call the signal function again, so that in order to minimize the signal processing function is reverted to the default processing time window, Figure 10.6 is a program written according to this rule, but the program in the traditional system V platform does not work well, its output will be a continuous string "SIGCLD received", most of the process due to stack space overflow and abnormally terminated.
#include "apue.h"
#include <sys/wait.h>
static void sig_cld(int signo);
int main()
{
pid_t pid;
if(signal(SIGCLD, sig_cld) == SIG_ERR)
perror("signal error");
if((pid = fork()) < 0)
{
perror("fork error");
}
else if(pid == 0)
{
/* child process*/
sleep(2);
_exit(0);
}
pause(); /*parent process*/
exit(0);
}
static void sig_cld(int signo)
{
pid_t pid;
int status;
printf("SIGCLD received\n");
if(signal(SIGCLD, sig_cld) == SIG_ERR) /*reestablish handler*/
perror("signal error");
if((pid = wait(&status)) < 0) /*fetch child status*/
perror("wait error");
printf("pid = %d\n", pid);
}
The problem with the above procedure is that the function signal is called at the beginning of the signal processing function, which corresponds to the second item discussed above – The kernel checks to see if there is a child process that requires wait for (which is the case in the above procedure because we are processing the SIGCLD signal), So the call to the signal function produces another call to the signal handler function, which in turn invokes the signal function, and the entire process repeats itself.
In order to solve the problem of the above procedure, we must move the call to the function signal to the wait function, and by doing so we call the signal function after capturing the terminating state of the child process, and the signal will be generated only when the other child processes are terminated.
POSIX.1 statement: When we establish SIGCHLD signal processing function, if there is a child process that has not yet been stopped wait, whether the signal needs to be generated and not specified, so the above is allowed, but for posix.1, after the signal is generated, the signal processing function will not be reset to the default function (Assuming that we are using the posix.1 sigaction function to set the signal handler function), there is no need to call the function signal again in the signal handler function. So the above problem disappears.
From for notes (Wiz)
10.7 SIGCHLD Definition