As Charlie Burns pointed out, both processes eventually exit as a consequence of the signal, but for different reasons.
Child
During its sleep, the child is blocked in a system call (the actual system call is nanosleep
, used to implement the sleep()
function). When a process receives a signal while in a system call, the corresponding signal handler is executed and the system call returns an error, EINTR
, which means it has been interrupted and couldn't fulfill its duty. You can then decide if you want to restart the system call or not. Upon receiving SIGUSR1, the nanosleep system call executed by the child is interrupted, the handler is executed and sleep() returns immediately. Notice what man 3 sleep
says about the return value of sleep():
Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted by a signal handler.
The correct way would be for the child to check for the return value of sleep (number of seconds left to sleep), and sleep again for that duration.
Parent
Unlike what Charlie Burns pointed out, waitpid() in the parent does not return because of the child receiving a signal. It returns because of the child exiting. It would return because of the child IF the child did not handle the signal, and thus was killed by it (an unhandled signal causes the process to die). You can (and should) check that using the WIFEXITED macro and its companions as described in man 2 waitpid
. The example at the bottom of this man page is very good:
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d
", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d
", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d
", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued
");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
Basically, what this code does is wait on the child until it has exited normally or has exited because of an unhandled signal. In your case, it would be a good idea for the parent to check the status variable to make sure that waitpid returned because of the event it expects (a child exiting) and not something else.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…