Waiting for a Child Process and then Checking its Status
The following example demonstrates the use of waitpid(), fork(),
and the macros used to interpret the status value returned by
waitpid() (and wait()). The code segment creates a child process
which does some unspecified work. Meanwhile the parent loops
performing calls to waitpid() to monitor the status of the child.
The loop terminates when child termination is detected.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
...
pid_t child_pid, wpid;
int status;
child_pid = fork();
if (child_pid == -1) { /* fork() failed */
perror("fork");
exit(EXIT_FAILURE);
}
if (child_pid == 0) { /* This is the child */
/* Child does some work and then terminates */
...
} else { /* This is the parent */
do {
wpid = waitpid(child_pid, &status, WUNTRACED
#ifdef WCONTINUED /* Not all implementations support this */
| WCONTINUED
#endif
);
if (wpid == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("child exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("child killed (signal %d)\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("child stopped (signal %d)\n", WSTOPSIG(status));
#ifdef WIFCONTINUED /* Not all implementations support this */
} else if (WIFCONTINUED(status)) {
printf("child continued\n");
#endif
} else { /* Non-standard case -- may never happen */
printf("Unexpected status (0x%x)\n", status);
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
Waiting for a Child Process in a Signal Handler for SIGCHLD
The following example demonstrates how to use waitpid() in a
signal handler for SIGCHLD without passing -1 as the pid
argument. (See the APPLICATION USAGE section below for the
reasons why passing a pid of -1 is not recommended.) The method
used here relies on the standard behavior of waitpid() when
SIGCHLD is blocked. On historical non-conforming systems, the
status of some child processes might not be reported.
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define CHILDREN 10
static void
handle_sigchld(int signum, siginfo_t *sinfo, void *unused)
{
int sav_errno = errno;
int status;
/*
* Obtain status information for the child which
* caused the SIGCHLD signal and write its exit code
* to stdout.
*/
if (sinfo->si_code != CLD_EXITED)
{
static char msg[] = "wrong si_code\n";
write(2, msg, sizeof msg - 1);
}
else if (waitpid(sinfo->si_pid, &status, 0) == -1)
{
static char msg[] = "waitpid() failed\n";
write(2, msg, sizeof msg - 1);
}
else if (!WIFEXITED(status))
{
static char msg[] = "WIFEXITED was false\n";
write(2, msg, sizeof msg - 1);
}
else
{
int code = WEXITSTATUS(status);
char buf[2];
buf[0] = '0' + code;
buf[1] = '\n';
write(1, buf, 2);
}
errno = sav_errno;
}
int
main(void)
{
int i;
pid_t pid;
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handle_sigchld;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction");
exit(EXIT_FAILURE);
}
for (i = 0; i < CHILDREN; i++)
{
switch (pid = fork())
{
case -1:
perror("fork");
exit(EXIT_FAILURE);
case 0:
sleep(2);
_exit(i);
}
}
/* Wait for all the SIGCHLD signals, then terminate on SIGALRM */
alarm(3);
for (;;)
pause();
return 0; /* NOTREACHED */
}