Ответ 1
Моя первая мысль - некорректная обработка сигнала, но в вашем сообщении недостаточно информации для написания тестового кода для репликации вашего сбоя. Но я могу дать вам несколько мест, чтобы посмотреть. Простите меня, если я расскажу о нескольких основах сигнала, которые вы уже знаете для будущих читателей.
Прежде всего, я не знаю, используете ли вы устаревший сигнал() или новые сигнальные процедуры POSIX sigaction(), чтобы поймать сигналы. sigset() полезен между GNU.
Устаревшие сигналы - сигнал()
Это почти невозможно, если не невозможно, гарантировать герметичный процессор сигналов с использованием исходного процессора сигналов во всех средах.
- В некоторых системах UNIX, входящих в обработчик сигнала, может reset обработчик к состоянию по умолчанию. Последующие сигналы гарантированно теряются, если обработчик явно не примет сигнал reset.
- Обработчики сигналов() не должны предполагать, что они вызываются один раз для каждого сигнала.
- Обработчики должны выполнять цикл
while( ( pid = waitpid( -1, &signal, WNOHANG ) ) > 0 )
, пока не будет найдено больше сигналов, поскольку устаревшие сигналы устанавливают условие bool показывая хотя бы один сигнал. Фактический счет неизвестен. - Обработчики должны допускать, чтобы сигналы не были обнаружены, если обработанный ранее цикл while() сигнал.
- Обработчики должны выполнять цикл
- Разрешить сигналы от неизвестных процессов... если запущенная программа также запускается процесс внука вы можете наследовать этот процесс, если ваш ребенок быстро выйдет.
Совет, держите нос и убегайте от устаревших сигналов.
Отсутствие цикла while() в устаревшем обработчике и нескольких SIGCHILD, один из вашего sudo и один или несколько из неожиданных внуков, выпущенных sudo. Если обрабатывается только один SIGCHILD, когда сигнал внука входит первым, ожидаемый программный сигнал не будет улавливаться.
Сигналы POSIX - sigaction() Сигналы POSIX могут очищать все сбои устаревших сигналов.
- Установить обработчик без восстановления (восстановление НЕ является частью сигналов POSIX и часто, по крайней мере, на мой взгляд, зло, когда вы можете получить более одного сигнала для обработки таким же образом).
- Сигналы sigaction() являются липкими... они живут, пока явно не изменились (замечательно!). Ничего из этого сложного требования, связанного с необходимостью reset обработчика сигнала в обработчике.
- Установите маску для маскировки текущего сигнала при обработке сигнала. Параноиды также маскируют любой другой сигнал, передаваемый тому же обработчику.
Недостаток маски может вызвать странные вещи, такие как потеря трека сигнала, если вы получаете SIGCHILD, находясь в обработчике SIGCHILD.
GNU - sigset()
GNU обеспечивает полезную промежуточную связь, которая имеет те же сигнатуры вызова, что и signal(), но устраняет большинство проблем. Также доступны некоторые дополнительные функции управления. Использование sigset() является простым решением для многих проблем с сигналами.
Напоминания
Подумайте о обработчиках сигналов в виде потоков в вашей программе,
даже если вы в противном случае не используете потоки в коде.
В старые времена вам нужно было сделать абсолютно минимальную обработку обработчиков сигналов... отсутствие вызова библиотечного кода, таких как printf, которые имеют побочные эффекты. Я по-прежнему придерживаюсь этого, когда нужно использовать устаревшие обработчики сигналов и всегда использовать многопоточные предупреждения в новых обработчиках.