Улавливающий сигнал внутри собственного обработчика

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

void handler(int signo)
{
    printf("Into handler\n");
    while(1);
}
int main()
{
    struct sigaction act;
    act.sa_handler = handler;
    act.sa_flags = 0;
    sigemptyset(& act.sa_mask);
    sigaction(SIGINT, &act, NULL);
    while(1);
    return 0;
}

После перехвата KeyboardInterrupt один раз, когда я снова нажимаю "Ctrl + C", SIGINT не обрабатывается... Я предполагаю, что "В обработчик" должен печататься каждый раз, когда я нажимаю "Ctrl + C" .

Я хочу поймать SIGINT внутри самого обработчика SIGINT().

Ответ 1

Вам нужно установить SA_NODEFER на sa_mask, чтобы поймать тот же сигнал, что и тот, который вы сейчас обрабатываете:

SA_NODEFER: не препятствуйте принятию сигнала из собственного обработчика сигнала. SA_NOMASK является устаревшим нестандартным синонимом для этого флага.

Ответ 2

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

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

Вызов printf из обработчика сигнала - undefined. Это может привести к сбою вашей программы. Список функций, которые вы фактически можете безопасно вызывать из обработчика сигнала, очень ограничен. Мне нужен список функций безопасности с использованием Async-Signal Safe из glibc

Ответ 3

Использование функции printf в обработчике сигналов не является хорошей идеей для использования, так как это может привести к поведению undefined! В образце кода отсутствует жизненно важный бит для обработчика сигналов. Посмотрите на мой блог об этом здесь в 'Q6, Как уловить ошибку сегментации?

Кроме того, вам нужно заменить цикл while на что-то более надежное как способ выйти из программы во время тестирования обработчика сигнала... например... как вы его уходите?

Ответ 4

Вы можете использовать что-то вроде этого вместо printf:

const char *str = "Into handler\n";
write(1, str, strlen(str));

Функция write(..) безопасна для вызова из сигнального hanlder. Не забудьте включить заголовок unistd.h, чтобы использовать его.

Ответ 5

"while (1)" в обработчике препятствует возврату первого служебного вызова. Удалите это, и последующие прерывания должны снова вызвать обработчик.

Процедура обслуживания прерываний не должна препятствовать возврату вызывающего потока.