Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling multiple SIGCHLD

Tags:

In a system running Linux 2.6.35+ my program creates many child processes and monitors them. If a child process dies I do some clean-up and spawn the process again. I use signalfd() to get the SIGCHLD signal in my process. signalfd is used asynchronously using libevent.

When using signal handlers for non-real time signals, while the signal handler is running for a particular signal further occurrence of the same signal has to be blocked to avoid getting into recursive handlers. If multiple signals arrive at that time then kernel invokes the handler only once (when the signal is unblocked).

Is it the same behavior when using signalfd() as well? Since signalfd based handling doesn't have the typical problems associated with the asynchronous execution of the normal signal handlers I was thinking kernel can queue all the further occurrences of SIGCHLD?

Can anyone clarify the Linux behavior in this case ...

like image 232
Manohar Avatar asked Dec 06 '11 10:12

Manohar


People also ask

How do you handle the SIGCHLD signal?

When a child process stops or terminates, SIGCHLD is sent to the parent process. The default response to the signal is to ignore it. The signal can be caught and the exit status from the child process can be obtained by immediately calling wait(2) and wait3(3C).

What is the use of SIGCHLD signal?

Sends a SIGCHLD signal to the parent process to indicate that the child process has ended. Saves the exit status of the child process so that the parent process can identify which child process (by process ID) ended and its exit status.

Which is the default action for SIGCHLD?

Note that the default action for SIGCHLD is to ignore this signal; nevertheless signal(SIGCHLD, SIG_IGN) has effect, namely that of preventing the transformation of children into zombies.

Does child process inherit signal handler?

a child process inherits signal settings from its parent during fork (). When process performs exec (), previously ignored signals remain ignored but installed handlers are set back to the default handler.


1 Answers

On Linux, multiple children terminating before you read a SIGCHLD with signalfd() will be compressed into a single SIGCHLD. This means that when you read the SIGCHLD signal, you have to clean up after all children that have terminated:

// Do this after you've read() a SIGCHLD from the signalfd file descriptor: while (1) {     int status;     pid_t pid = waitpid(-1, &status, WNOHANG);     if (pid <= 0) {         break;     }     // something happened with child 'pid', do something about it...     // Details are in 'status', see waitpid() manpage } 

I should note that I have in fact seen this signal compression when two child processed terminated at the same time. If I did only a single waitpid(), one of the children that terminated was not handled; and the above loop fixed it.

Corresponding documentation:

  • http://man7.org/linux/man-pages/man7/signal.7.html "By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued"
  • http://man7.org/linux/man-pages/man3/sigwait.3p.html "If prior to the call to sigwait() there are multiple pending instances of a single signal number, it is implementation-defined whether upon successful return there are any remaining pending signals for that signal number."
like image 173
Ambroz Bizjak Avatar answered Sep 19 '22 17:09

Ambroz Bizjak