1

I see some example of SIGCHLD handler like:

void child()                                                                                                                  
{                                                                                                                    
    wait(0);                                                                                                          
    signal(SIGCHLD, child);      
}  
void server_main()
{
    ...
    signal(SIGCHLD, child);
    ...
    for(;;;) {
        ...
        switch(fork()) {
        ...
        }
    }

There two parts in the handler that confuse me: 1). SIGCHLD is caught when the child terminates or is stopped. Then why need to call wait inside the handler? The signal already arrives. 2). Why need to reinstall the SIGCHLD handler. Isn't the signal call will install the handler once and for all?

Thanks!

Oxdeadbeef
  • 1,033
  • 2
  • 11
  • 26

2 Answers2

2
  1. SIGCHLD will be triggered when the child process finished execution. It will however still be in the process table (as a so-called zombie process) in order to let the parent fetch the exit value of the child. Calling wait() will clear the process table from that child process.
  2. If you only create n child processes then there's no reason for the signal handler still being in place when all n child processes died.

I suggest you take a look at sigaction instead, as the behaviour of signal varies between Unixes.

halfdan
  • 33,545
  • 8
  • 78
  • 87
  • thanks, i see the first point. for the second one, the signal handler is installed for the parent right? why when multiple child processes died may cause the signal handler to be not in effect? – Oxdeadbeef Dec 08 '11 at 00:09
  • Please have a look at the explanation by sarnold, he explained it quite good. – halfdan Dec 08 '11 at 00:11
1

Isn't the signal call will install the handler once and for all?

You cannot rely on this behavior; perhaps the signal handler will be cleared, perhaps it will persist. This is part of the problem with historical signal handling. The signal(3) manpage on my system reports:

   When a signal occurs, and func points to a function, it is
   implementation-defined whether the equivalent of a:


          signal(sig, SIG_DFL);

   is executed or the implementation prevents some
   implementation-defined set of signals (at least including
   sig) from occurring until the current signal handling has
   completed.

Unreliable signals have been nearly replaced by sigaction(2)-based signals introduced in SysVr4 and standardized in POSIX.1-2001:

   struct sigaction {
      void     (*sa_handler)(int);
      void     (*sa_sigaction)(int, siginfo_t *, void *);
      sigset_t   sa_mask;
      int        sa_flags;
      void     (*sa_restorer)(void);
   };

   int sigaction(int signum, const struct sigaction *act,
                 struct sigaction *oldact);

These are sadly more complicated to write, but once you've written the code, you won't have to wonder if you need to re-install your handler -- and you won't have to worry that the signal will arrive a second time while handling the signal.

sarnold
  • 102,305
  • 22
  • 181
  • 238