Сигнал доставляется в определенный поток, поэтому обработчик сигнала работает в определенном потоке (поток, в который был доставлен сигнал). Если сигнал доставляется в поток, записывающий 222\n
, то этот поток должен прекратить запись в 222\n
и запустить обработчик сигнала. Ваш примерный обработчик сигнала занимает целую секунду, так что это полная секунда, в течение которой этот поток может не записать 222\n
.
Кроме того, поскольку вы используете printf
для записи всех этих байтов, в libc выполняется некоторая блокировка. Так как printf
не является функцией, безопасной для асинхронных сигналов, фактически не определено, что произойдет, если вы будете использовать ее в обработчике сигналов. Одно из возможных объяснений поведения, которое вы наблюдаете, заключается в следующем. Если сигнал доставляется потоку, пока этот поток удерживает блокировку stdout, никакой другой поток не сможет записывать в stdout до тех пор, пока обработчик не вернется и блокировка не будет снята «нормальным» кодом, выполняющимся в этом потоке. В этом случае обработчик сигнала все еще может записывать в стандартный вывод, поскольку блокировка - это rlock , которая может быть повторно получена любым конкретным потоком. Однако это может варьироваться в зависимости от конкретной платформы, библиотеки C, библиотеки потоков или фазы луны. Ваш пример легко конвертируется в использование write (2), хотя оно демонстрирует более или менее одинаковое поведение проблемы, имеет более или менее такое же исправление и не полагается на неопределенное поведение.
Если вы используете SIG_BLOCK
сигнал таймера в потоках 222\n
, то обработчик сигнала всегда будет работать в главном потоке, и вы продолжите получать 222\n
вывод, пока обработчик сигнала спит.
Сет также делает большое замечание только об использовании безопасных функций в обработчиках сигналов. Использование любых других означает, что поведение вашей программы не определено.