При записи в канал, как в вашем примере, STDOUT буферизуется по умолчанию.Это означает, что print "foo\n"
в вашем коде не сразу записывает в STDOUT, а записывает в буфер, и буфер будет очищаться (записываться в STDOUT) только тогда, когда он полон или является частью очистки программы.Использование strace
для просмотра того, что на самом деле делает ваша программа, показывает, что она сначала восстанавливает обработчики сигналов как часть очистки программы, а затем записывает в STDOUT, что приводит к SIGPIPE, который больше не обрабатывается вашим сабвуфером и, таким образом, приводит к уничтожениюпрограммы.
Если вы убедитесь, что вывод выполняется немедленно, а не при очистке программы, ваш обработчик сигнала будет успешно запущен.Это можно сделать, отключив буферизацию STDOUT с помощью $|=1
:
$ perl -e \
'$|=1; $SIG{PIPE} = sub { print STDERR "XXX\n"; }; sleep(1); print "foo\n";' \
| echo -n
output: XXX
Другими словами: если ваш обработчик сигнала работает, он работает отлично, и это был только артефакт вашего конкретного использования, который он не вызвал.Почему он не сбрасывает обработчик сигнала с игнорирования (SIG_IGN
) на значение по умолчанию (SIG_DFL
) при выходе и, таким образом, показывает ту же проблему с IGNORE, которого я не знаю.