Переустановка обработчика SIGCHLD

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

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

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

Спасибо!

2 ответа

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

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

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

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

   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);

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

Другие вопросы по тегам