Переустановка обработчика SIGCHLD - PullRequest
1 голос
/ 08 декабря 2011

Я вижу пример обработчика SIGCHLD, например:

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

В обработчике есть две части, которые меня смущают: 1).SIGCHLD пойман, когда ребенок заканчивается или остановлен.Тогда зачем нужно вызывать wait внутри обработчика?Сигнал уже поступает.2).Зачем нужно переустанавливать обработчик SIGCHLD.Разве сигнал вызова не установит обработчик раз и навсегда?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 08 декабря 2011
  1. SIGCHLD будет запущен после завершения дочернего процесса выполнение. Однако он все еще будет в таблице процессов (как так называемый процесс зомби), чтобы позволить родителю выбрать выход ценность ребенка. Вызов wait() очистит таблицу процессов из этого дочернего процесса.
  2. Если вы создаете только n дочерние процессы, то нет никаких оснований для того, чтобы обработчик сигналов оставался на месте, когда все n дочерние процессы умерли.

Я предлагаю вам вместо этого взглянуть на sigaction, поскольку поведение signal варьируется в зависимости от Unixes.

1 голос
/ 08 декабря 2011

Разве сигнал вызова не установит обработчик раз и навсегда?

Вы не можете полагаться на это поведение; возможно, обработчик сигнала будет очищен, возможно, он сохранится. Это часть проблемы с исторической обработкой сигналов. Справочная страница signal(3) в моей системе сообщает:

   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.

Ненадежные сигналы были почти заменены сигналами sigaction(2), введенными в SysVr4 и стандартизированными в 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);

К сожалению, их сложнее написать, но как только вы напишете код, вам не придется задумываться, нужно ли вам переустанавливать свой обработчик, и вам не придется беспокоиться о том, что сигнал будет прибыть во второй раз при обработке сигнала.

...