int main()
{
pid_t pid = fork();
if (pid > 0) {
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGCHLD);
int signum;
sigwait(&sigset, &signum);
if (signum == SIGCHLD) printf("Child exited\n");
}
if (pid == 0) {
sleep(2);
exit(0);
}
}
Why not use wait() or waitpid()?
Using sigwait() with SIGCHLD should work just fine. Your program,
however, violates a requirement of sigwait(). To quote the SUS
description of sigwait() at www.unix.org:
The signals defined by 'set' shall have been blocked at
the time of the call to sigwait(); otherwise, the behavior
is undefined.
That requirement applies to *all* signals used with sigwait(), but it
would not surprise me to learn that some OSes were more forgiving for
some signals than for others (like SIGCHLD).
So, add a call to sigprocmask() (or pthread_sigmask() if this is a
threaded program) to block the involved signals before calling
sigwait() and try it again.
Philip Guenther
> Can sigwait be used to catch an exiting child process? I can't seem
> to get it to work for some reason. In the following program, the
> parent process hangs forever and sigwait does not respond to a
> SIGCHLD. An old-fashioned signal handler works fine, but sigwait
> doesn't.
You have to install a signal handler for SIGCHLD in any case, it is
ignored by default.
> Are there certain signals that won't work with sigwait?
Another thing is that the signal(s) you are going to wait with
sigwait() must be blocked prior to the call, otherwise you are
introducing race conditions. Please read
http://www.opengroup.org/onlinepubs/000095399/functions/sigwait.html
Working example:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void sig_hand(int) {}
int main()
{
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigset, NULL);
signal(SIGCHLD, sig_hand);
pid_t pid = fork();
if(pid > 0)
{
int signum;
sigwait(&sigset, &signum);
if(signum == SIGCHLD)
printf("Child exited\n");
}
else if(pid == 0)
{
sleep(2);
}
}