How can I handle SIGCHLD?

kanoz picture kanoz · Aug 24, 2011 · Viewed 47.1k times · Source

I need to handle SIGCHLD properly. How can I use it with my existing code? at the moment I cant wait for the child process unless I use 0 instead of WNOHANG|WUNTRACED.

status = 0; 
pid_t child, endID;

if(amp == 1)
        signal( SIGCHLD, SIG_IGN ); 

child = fork(); 

if (child  <  0) {    
        perror("fork() error\n");
        exit(EXIT_FAILURE);

} else if (child == 0) { 
        // do sth here
        perror("error\n");

} else { 
        //sleep(1)

If I remove sleep then parent is executed 1st.. why?

Answer

cnicutar picture cnicutar · Aug 24, 2011

Here is a start (but read below):

static void
child_handler(int sig)
{
    pid_t pid;
    int status;

    /* EEEEXTEERMINAAATE! */
    while((pid = waitpid(-1, &status, WNOHANG)) > 0)
        ;
}

/* Establish handler. */
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = child_handler;

sigaction(SIGCHLD, &sa, NULL);

Of course, this is all pointless. If the parent simply ignores SIGCHLD, the children are silently reaped and won't turn into zombies.

Quoting TLPI:

Explicitly setting the disposition of SIGCHLD to SIG_IGN causes any child process that subsequently terminates to be immediately removed from the system instead of being converted into a zombie.

So something like this should do the trick for you:

signal(SIGCHLD, SIG_IGN); /* Silently (and portably) reap children. */