If I am correct, a process waits for its children to terminate or stop by calling the waitpid() or wait() function.

What is the relation between SIGCHLD signal and the waitpid() orwait() functions?

  • Is it correct that when a process calls the waitpid() or wait() functions, the process suspends itself until a child process terminates/stops, which is the same as until a SIGCHLD signal is sent to it?

    (pause() suspends the current process until any signal is sent to it. So I wonder if waitpid() is similar, except that until SIGCHLD is sent to it?)

  • When SIGCHLD is sent to a process which has been suspended by calling waitpid(), what is the order between executing SIGCHLD handler and resuming from suspension by waitpid()?
    ( In the following example from Computer Systems: a Programmer's Perspective, the SIGCHLD handler calls waitpid().)


void handler(int sig)
  int olderrno = errno;

  while (waitpid(-1, NULL, 0) > 0) {
    Sio_puts("Handler reaped child\n");
  if (errno != ECHILD)
    Sio_error("waitpid error");
  errno = olderrno;

int main()
  int i, n;
  char buf[MAXBUF];

  if (signal(SIGCHLD, handler1) == SIG_ERR)
    unix_error("signal error");

  /* Parent creates children */
  for (i = 0; i < 3; i++) {
    if (Fork() == 0) {
      printf("Hello from child %d\n", (int)getpid());

  /* Parent waits for terminal input and then processes it */
  if ((n = read(STDIN_FILENO, buf, sizeof(buf))) < 0)

  printf("Parent processing input\n");
  while (1)

  • 1
    Could you reword your question to make it a real question? What do you like to be answered?
    – schily
    Oct 27 '20 at 8:38

If installed, the signal handler is invoked by the kernel in the process when a child changes state (typically, exiting.) but it does not, by default, reap the child. A wait(2) or waitpid(2) call from inside or outside the handler is still needed for the child to be reaped. If SA_NOCLDWAIT is specified as an option to sigaction(2) when installing the SIGCHLD handler, then the kernel will automatically reap the child after the signal handler is delivered and no wait(2) call is needed to reap.

See the discussion of SA_NOCLDSTOP and SA_NOCLDWAIT options in the sigaction(2) man page as they relate to SIGCHLD.

Also, consider using sigaction(2) instead of signal(2) and allows you to use the three argument signal handler by specifying SA_SIGINFO. The siginfo_t structure reference will have additional, useful information as to why SIGCHLD is being delivered.

  • Thanks. (1) Are SIGCHLD signal and its handler used only in asychronous manner? (2) If a program installs a handler for SIGCHLD, and then calls fork() and waitpid() or wait(), what will happen when a child terminates? Does waitpid() or wait() return first and then the signal handler for SIGCHLD is invoked, or is the signal handler is invoked first and then waitpid() or wait() returns?
    – Tim
    Dec 6 '20 at 22:18
  • For (1), there is a block or non blocking option for the waitpid call. As per here. stackoverflow.com/questions/51094945/…
    – Chai Ang
    Dec 21 '20 at 4:02

wait() is an outdated UNIX system call from the 1970s and waitpid() is an outdated UNIX system call from the 1980s.

In 1988, the superior interface waitid() has been introduced.

signal() is also an outdated interface from the 1970s. The recent interface is called sigaction() and allows to control the behavior of signals. A typical call in your case would be:

    struct sigaction sa; 

    sa.sa_sigaction = handler; 
    sa.sa_flags = SA_RESTART|SA_SIGINFO; 

    sigaction(SIGCHLD, &sa, NULL); 

If you add SA_NOCLDWAIT to sa.sa_flags, you do not need to call wait*() at all and the system will not keep zombie processes until a wait*() call is made.

If you add SA_NOCLDSTOP, the SIGCHLD handler will not be called if a cild process exits.

If a SIGCHLDis generated, that would call a function:

void handler(int sig, siginfo_t *sip, void *context)

when a child process died. The parameter sig is filled with the signal number SIGCHLD and the second parameter is filled with the same information as you get from a call to waitid(), as in:

struct siginfo si;

ret = waitid(P_PID, pid, &si, WEXITED|WSTOPPED|WTRAPPED);

So if you are not interested in the status of the childs, it is possible to tell the system and if you are not interested in calling wait*(), but still like to get the process status, you can tell the system and use the information from the second parameter of the signal handler function.

When a child process died and struct siginfo is examined, the following fields are filled out:

si.si_signo   /* The signal number SIGCHLD */
si.si_code    /* The reason for the child to exit */
si.si_status  /* Either the parameter to exit(r) or signal number */
si.si_pid     /* The process is of the child that died */

If si.si_code contains the value CLD_EXITED, then si.si_status (on a POSIX system) contains the full 32 bits of the exit() code.

If si.si_code contains CLD_KILLED, CLD_DUMPED, CLD_TRAPPED, CLD_STOPPED or CLD_CONTINUED, then si.si_code contains the signal number that caused the status change.


I dont have enough points to comment but this should answer your question.


The signal raised will trigger the handler function you set for that specific signal type, which is SIGCHLD in your example.

Example here. https://stackoverflow.com/questions/13792900/signal-and-sigchld-what-does-it-do

As you can see in the link just above, the wait() doesnt have to be inside the handler.

That just waits for the child process to terminate.

So basically, there is no direct relationship as such, just that a SIGCHLD signal will be generated when a forked child process dies and that a wait() will wait till the child process terminates properly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.