Как получить более двух последовательных сигналов?

Если я отправлю несколько последующих Hangup сигналы для следующей программы, только две из них будут обработаны, а остальные будут игнорироваться:

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

int id;
void handler(int s)
{
    id++;
    int i;
    for(i=0; i<3; i++)
    {
        printf("Sig %d\n", id);
        sleep(2);
    }
}

int main()
{
    int i;
    signal(SIGHUP, handler);
    for( i=0; ; i++ )
    {
        printf("%d\n", i);
        sleep(1);
    }
    return 0;
}

Я использую следующую команду для отправки сигнала процессу:

kill -l {#process}

Если я выполню указанную выше команду три раза подряд, третий сигнал будет проигнорирован, как показано в следующем выводе:

0
1
2
3
4
5
6
7
Sig 1
Sig 1
Sig 1
Sig 2
Sig 2
Sig 2
8
9
10
11
12

Есть ли способ поймать третий сигнал тоже?

2 ответа

Решение

Как правило, вы не можете сделать это со стандартными сигналами. Ядро Unix обычно ставит в очередь только один ожидающий сигнал. Если Sig2 и Sig3 отправляются во время ожидания процесса в обработчике Sig1, они объединяются.

Вы можете использовать sigaction(2) для настройки вашего обработчика сигнала и установки для него флага SA_NODEFER. Это позволит доставлять новый сигнал, пока он находится в обработчике сигнала. Убедитесь, что ваш обработчик является реентерабельным, это подвержено ошибкам решение.

Также есть расширение POSIX.1b (POSIX.1-2001), называемое "сигналы в реальном времени". Такие сигналы могут быть поставлены в очередь несколько раз, но SIGHUP не является одним из них. signal(7) в Linux утверждает, что сигналы в реальном времени пронумерованы от 33 (SIGRTMIN) до 64 (SIGRTMAX).

В Linux ожидающие сигналы представлены только одним битом. Это означает, что если несколько сигналов генерируются, когда обработчик уже запущен, он будет вызван только еще раз.

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