Помимо проблемы «слишком много сигналов», сигналы могут быть явно проигнорированы. От man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Сигналы также могут быть заблокированы. От man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
И заблокированные, и игнорируемые наборы сигналов наследуются дочерними процессами, поэтому может случиться, что родительский процесс вашего приложения проигнорирует или заблокирует один из этих сигналов.
Что происходит, когда несколько сигналов доставляются до того, как процесс завершит обработку предыдущих? Это зависит от ОС. signal(2)
Страница руководства связана выше рассуждает по поводу его:
- Система V сбросит расположение сигнала на значение по умолчанию. Хуже того, быстрая доставка нескольких сигналов приведет к рекурсивным (?) Вызовам.
- BSD автоматически блокирует сигнал, пока не будет завершен обработчик.
- В Linux это зависит от флагов компиляции, установленных для GNU
libc
, но я ожидаю, что поведение BSD.
signal(2)
настоятельно рекомендует вам избегать этой путаницы, используяsigaction(2)
вместо этого.Вы не можете поверить, что каждый отправленный сигнал будет доставлен. Например, ядро Linux «объединяет» SIGCHLD, если процессу требуется много времени для обработки SIGCHLD из вышедшего дочернего процесса.
Чтобы ответить на другую часть вашего вопроса, сигналы «ставятся в очередь» внутри ядра, если несколько разных сигналов поступают за слишком короткий промежуток времени.
Вы должны использовать
sigaction()
для настройки обработчика сигнала сsa_sigaction
членомsiginfo_t
, тщательно настраиваяsa_mask
членsiginfo_t
аргумента. Я думаю, что это означает, по крайней мере, маскирование всех «асинхронных» сигналов. Согласно man-странице для Linuxsigaction()
, вы также замаскируете обрабатываемый сигнал. Я думаю, что вы должны установитьsa_flags
член SA_SIGINFO, но я не могу вспомнить, почему у меня есть это суеверие. Я полагаю, что это сделает ваш процесс обработчиком сигналов, который остается установленным без условий гонки, и тот, который не прерывается большинством других сигналов.Напишите свою функцию обработчика сигнала очень, очень тщательно. По сути, просто установите глобальную переменную, чтобы указать, что сигнал был пойман, а остальная часть процесса должна обработать желаемое действие для этого сигнала. Таким образом, сигналы будут маскироваться в течение наименьшего количества времени.
Кроме того, вы захотите очень тщательно протестировать код обработки сигналов. Проведите небольшой тестовый процесс и отправьте как можно больше сигналов SIGUSR1 и SIGUSR2, возможно, из 2 или 3 специальных программ для отправки сигналов. Смешайте и некоторые другие сигналы, после того как вы уверены, что ваш код может обрабатывать SIGUSR1 и SIGUSR2 быстро и правильно. Приготовьтесь к трудной отладке.
Если вы используете Linux и только Linux, вы можете подумать о том,
signalfd()
чтобы создать дескриптор файла, который вы можете использовать,select()
или опросить для получения этих сигналов. Использованиеsignalfd()
может облегчить отладку.источник
Сигнал гарантированно доставляется в том смысле, что если процесс успешно вызывает
kill
, тогда цель получит сигнал. Это асинхронно: отправитель не может узнать, когда сигнал получен или обработан. Однако это не гарантирует, что сигнал будет доставлен. Цель может умереть, прежде чем сможет обработать сигнал. Если цель игнорирует сигнал во время его доставки, сигнал не будет иметь никакого эффекта. Если цель получает несколько экземпляров одного и того же номера сигнала, прежде чем она сможет их обработать, сигналы могут (и обычно) объединяются: если вы отправляете один и тот же сигнал дважды процессу, вы не можете знать, получит ли процесс сигнал один или два раза Сигналы в основном предназначены для уничтожения процесса или как способ заставить процесс обратить внимание, они не предназначены для связи как таковой.Если вам нужна надежная доставка, вам нужен другой механизм коммуникации. Существует два основных механизма связи между процессами: канал обеспечивает однонаправленную связь; сокет позволяет двунаправленную связь и несколько соединений к одному серверу. Если вам нужно, чтобы цель обрабатывала столько уведомлений, сколько отправляете, отправляйте байты по каналу.
источник
Ядро может объединять стандартные сигналы, если более одного доставлено во время блокировки. С другой стороны, сигналы в реальном времени не имеют аналогичных ограничений.
Из справочной страницы сигнала (7) :
Попробуйте использовать сигнал с номером в диапазоне от SIGRTMIN до SIGRTMAX.
источник
ulimit -i
показывает это значение как 63432 на Ubuntu 18.04.