Улавливающий сигнал внутри собственного обработчика
#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)" в обработчике препятствует возврату первого служебного вызова. Удалите это, и последующие прерывания должны снова вызвать обработчик.
Процедура обслуживания прерываний не должна препятствовать возврату вызывающего потока.