Tracking the death of a child process

codingfreak picture codingfreak · Mar 4, 2010 · Viewed 36.1k times · Source

How could I track down the death of a child process without making the parent process wait until the child process got killed?

I am trying a client-server scenario where the server accepts the connection from a client and forks a new process for each and every connection it accepts.

I am ignoring SIGCHLD signals to prevent zombie creation.

signal(SIGCHLD, SIG_IGN);
while(1)
{
  accept();
  clients++;
  if(fork() ==0)
  {
     childfunction();
     clients--;
  }
  else
  {
  }
}

The problem in the above scenario is that if the child process gets killed in the childfunction() function, the global variable clients is not getting decremented.

NOTE: I am looking for a solution without using SIGCHLD signal ... If possible

Answer

asveikau picture asveikau · Mar 4, 2010

Typically you write a handler for SIGCHLD which calls waitpid() on pid -1. You can use the return value from that to determine what pid died. For example:

void my_sigchld_handler(int sig)
{
    pid_t p;
    int status;

    while ((p=waitpid(-1, &status, WNOHANG)) != -1)
    {
       /* Handle the death of pid p */
    }
}

/* It's better to use sigaction() over signal().  You won't run into the
 * issue where BSD signal() acts one way and Linux or SysV acts another. */

struct sigaction sa;

memset(&sa, 0, sizeof(sa));
sa.sa_handler = my_sigchld_handler;

sigaction(SIGCHLD, &sa, NULL);

Alternatively you can call waitpid(pid, &status, 0) with the child's process ID specified, and synchronously wait for it to die. Or use WNOHANG to check its status without blocking.