Это то, что происходит в настоящее время: когда вы отправляете сигнал прерывания с клавиатуры, включается обработчик сигнала, записывает сообщение \nctrl-c has been pressed\n
на вашу консоль и устанавливает переменную should_stop
. Затем управление возвращается обратно в оператор read(0, &buf, 1)
. Поскольку stdin буферизуется, read
не закончится, пока не встретит символ новой строки. Если вы нажмете Enter
впоследствии - read
читает один бит и возвращается. После этого снова проверяется условие should_stop
, и поскольку оно теперь содержит значение 1
- l oop закончено.
Теперь мы хотим изменить это поведение, чтобы ваша программа корректно закрывалась вниз после SIGINT.
с man 7 signal
:
If a blocked call to one of the following interfaces is interrupted by a
signal handler, then the call is automatically restarted after the signal
handler returns if the SA_RESTART flag was used; otherwise the call fails
with the error EINTR:
с man 2 signal
:
certain blocking system calls are automatically
restarted if interrupted by a signal handler (see signal(7)). The BSD se‐
mantics are equivalent to calling sigaction(2) with the following flags:
sa.sa_flags = SA_RESTART;
Итак, вот как мы используем sigaction(2)
для нашего случая :
int main()
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = sighandler;
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
read_function();
write(1, "read_function is over\n", 22);
return (0);
}
Таким образом, при прерывании обработчиком сигнала read(2)
возвращается с ошибкой EINTR
и не перезапускается.
signal(2)
обычно уступает sigaction(2)
, когда Что касается переносимости кода, вы можете прочитать об этом здесь