Поймать сигнал внутри собственного обработчика - PullRequest
11 голосов
/ 10 марта 2010
#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 не обрабатывается ... Я намерен печатать «Into handler» каждый раз, когда я нажимаю «Ctrl + C» .

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

Ответы [ 5 ]

10 голосов
/ 10 марта 2010

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

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

6 голосов
/ 10 марта 2010

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

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

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

3 голосов
/ 10 марта 2010

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

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

2 голосов
/ 19 декабря 2014

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

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

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

1 голос
/ 10 марта 2010

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

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

...