Игнорирование сигнала на C - PullRequest
1 голос
/ 02 мая 2020

Это не вопрос кода, а теории.

У меня был этот код раньше:

void handler(int signal){
    printf("Handler called\n");
}

struct sigaction act;
act.sa_handler = &handler;
act.sa_flags = 0;


if (sigaction(SIGINT, &act, NULL) < 0){
    exit(1);
}

if (sigaction(SIGQUIT, &act, NULL) < 0){
    exit(1);
}

Когда я нажимал ctrl + C, вызывался обработчик, но Программа по-прежнему завершается.

И теперь, из любопытства, я попытался изменить флаги на SA_RESTART. Теперь он не выходит.

Почему?

1 Ответ

0 голосов
/ 02 мая 2020

SA_RESTART вызывает перезапуск системных прерываний EINTR (например, read) после доставки обработанного сигнала.

Так что если у вас было:

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

void handler(int signal)
{
    printf("Handler called\n");
}

int main()
{
    struct sigaction act;
    act.sa_handler = &handler;
    act.sa_flags = 0;
    if (sigaction(SIGINT, &act, NULL) < 0){ exit(1); }
    char ch; ssize_t nr;
    nr=read(0,&ch,1);
}

тогда с SA_RESTART это будет выглядеть так, как если бы строка nr=read(0,&ch,1); была заменена на

while(0>(nr=read(0,&ch,1)) && errno==EINTR){}`

. Обратите внимание, что в обработчиках сигналов следует вызывать только асин c -сигнал-безопасные функции. printf в обработчике обычно является рецептом неопределенного поведения, хотя в данном конкретном случае, когда вы только прерываете код, который сам по себе является асинхронным c -signal-safe (read), он довольно безопасен, хотя POSIX явно не санкционирует это (AFAIK).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...