Подтвердить что ты не робот

Обработка нескольких SIGCHLD

В системе под управлением Linux 2.6.35+ моя программа создает много дочерних процессов и контролирует их. Если дочерний процесс умирает, я делаю очистку и снова запускаю процесс. Я использую signalfd() для получения сигнала SIGCHLD в моем процессе. signalfd используется асинхронно, используя libevent.

При использовании обработчиков сигналов для сигналов не реального времени, в то время как обработчик сигналов работает для конкретного сигнала, дальнейшее обнаружение того же сигнала должно быть заблокировано, чтобы избежать попадания в рекурсивные обработчики. Если в это время поступает несколько сигналов, то ядро ​​вызывает обработчик только один раз (когда сигнал разблокирован).

Это то же поведение при использовании signalfd()? Поскольку обработка на основе signalfd не имеет типичных проблем, связанных с асинхронным выполнением нормальных обработчиков сигналов, я думал, что ядро ​​может поставить в очередь все последующие вхождения SIGCHLD?

Может ли кто-нибудь уточнить поведение Linux в этом случае...

4b9b3361

Ответ 1

В Linux несколько дочерних элементов, заканчивающихся до чтения SIGCHLD с помощью signalfd(), будут сжаты в один SIGCHLD. Это означает, что когда вы читаете сигнал SIGCHLD, вы должны очистить после завершения всех оставшихся детей:

// 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
}

Я должен отметить, что я действительно видел это сжатие сигнала, когда два дочерних обработанных завершались одновременно. Если я сделал только один waitpid(), один из оставшихся детей не был обработан; и указанная выше петля зафиксировала его.

Соответствующая документация:

  • http://man7.org/linux/man-pages/man7/signal.7.html "В отличие от этого, если несколько экземпляров стандартного сигнала доставляются, пока этот сигнал заблокирован, тогда только один экземпляр очередь"
  • http://man7.org/linux/man-pages/man3/sigwait.3p.html "Если перед вызовом sigwait() есть несколько ожидающих экземпляров одного номера сигнала, определяется, есть ли при успешном возврате любые оставшиеся ожидающие сигналы для этого номера сигнала."

Ответ 2

На самом деле бесполезным способом будет waitfd функционально, что позволит вам добавить конкретный pid для poll()/epoll(). К сожалению, он не был принят Linux несколько лет назад, когда он был предложен.