Обработка двух последовательных SIGTERM

Есть демон с двумя потоками: th1, th2. th2 читает сокет, используя read(2).

Если я убиваю демона с помощью SIGTERM, th1 ловит и обрабатывает сигнал (устанавливает флаг завершения), после этого вызывается деструктор демона, он вызывает pthread_kill(th2, SIGTERM). Однако второй поток не получает SIGTERM, поэтому он не уничтожается (когда сокет получает данные и выходит из read(), он завершает выполнение, так как установлен флаг завершения).

Если я позвоню pthread_kill(th2, SIGUSR2), а затем pthread_kill(th2, SIGTERM), все завершится корректно. Таким образом, похоже, что UNIX не позволяет последовательно отправлять одинаковые сигналы.

Зависит ли такое поведение от операционной системы? Можем ли мы гарантировать, что указанный поток получит SIGTERM из другого потока?


person vissi    schedule 03.08.2011    source источник
comment
Вы привлечете больше внимания к своему вопросу, если включите соответствующие теги языка программирования, c, c++ или yourLanguageHere. Удачи.   -  person shellter    schedule 03.08.2011
comment
Спасибо, добавил тег. Я предположил, что unix означает C )   -  person vissi    schedule 03.08.2011
comment
@vissi: это неправильно. Вы должны включать только тег языка, на котором вы работаете. Если ваш вопрос не касается функциональной совместимости, вы должны отмечать только один язык.   -  person Puppy    schedule 03.08.2011
comment
Покажите нам код, пожалуйста. Есть ли у th2 замаскированный SIGTERM? Вызывает ли th1 pthread_kill из собственного обработчика сигналов? Был ли установлен обработчик TERM SA_RESTART? Почему USR1 не завершает процесс — как вы с этим справляетесь?   -  person pilcrow    schedule 03.08.2011
comment
Кроме того, что вы имеете в виду, что хотите убить th2? Вы хотите просто прервать блокировку read()? Чтобы отменить запущенный поток? Чтобы подать определенный сигнал? Убить весь процесс?   -  person pilcrow    schedule 04.08.2011


Ответы (2)


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

Также имейте в виду, что в то время как pthread_kill() отправляет сигнал в заданный поток для обработки, фактическая обработка сигнала имеет глобальный эффект (т. е. обработчики сигналов относятся к процессу, а не к потоку).

Вы также можете захотеть изучить явный вызов pthread_cancel(), поскольку read() является допустимой точкой отмены. При необходимости вы можете добавить обработчик отмены, а также заблокировать состояние отмены потока, если вы используете функции, которые не являются безопасными при отмене. Вы можете прочитать несколько советов по использованию pthread_cancel() здесь.

person Jason    schedule 03.08.2011
comment
sigaction() и SA_SIGINFO совершенно ортогональны поведению очереди сигналов POSIX в реальном времени - было бы неточно сказать, что они включают семантику в реальном времени. Более того, ошибочно предполагать, что эту семантику можно включить во время выполнения. Сигналы реального времени (SIGRTMIN .. SIGRTMAX) всегда стоят в очереди, а стандартные сигналы — нет. (Спецификация позволяет, но на практике нет.) - person pilcrow; 04.08.2011
comment
Хорошо, вот где возникло мое замешательство ... из спецификаций (а не из реализации, как я предполагаю, в Linux) казалось, что стандартные сигналы также будут поставлены в очередь в дополнение к сигналам реального времени, если вы использовали sigaction() для установки SA_SIGINFO для стандартного типа сигнала. Спасибо за разъяснение этого ... Я обновлю свой ответ. - person Jason; 04.08.2011

Относительно старомодный, но эффективный подход заключается в использовании select() и конвейера для повторной отправки сигналов всем потокам. (Вы выбираете() в своем дескрипторе блокировки и дескрипторе чтения канала).

person Joshua    schedule 03.08.2011