Можно ли определить, какую трубу выбросил SIGPIPE?
Я пытаюсь разобраться с сервером, который работает следующим образом:
- У него есть родительский процесс
- Создает "вспомогательный" дочерний процесс для обработки некоторых специальных задач.
- Он открывает дочерний процесс с помощью трубы; и использует канал, чтобы выдавать команды ребенку.
- Он также порождает многие другие дочерние процессы (главная цель сервера - выполнять различные команды).
Я хотел бы быть в состоянии определить, когда запись в канал в дочерний процесс не удается; и выдать специальное уведомление.
Обычно я достиг бы этого, создав $SIG{PIPE}
обработчик в родительском процессе.
Однако меня беспокоит тот факт, что некоторые процессы, которые родитель запускает для выполнения команд, могут иметь свои собственные каналы, открытые для них; и если запись в эти каналы не удалась, я бы просто проигнорировал SIGPIPE.
Q1. Есть ли способ для меня, чтобы сказать из обработчика SIGPIPE, какой из открытых каналов бросил сигнал? (Я знаю PID каждого ребенка, так что PID будет в порядке... или если есть способ сделать это с помощью файлового дескриптора #s?).
Q2. Могу ли я решить проблему с помощью local $SIG{PIPE}
каким-то образом? Я предполагаю, что мне нужно:
- Установить вспомогательный процесс
local $SIG{PIPE}
прямо перед записью в эту трубу - делать
print $HELPER_PIPE
(это происходит только в одной подпрограмме) - Сбросить $SIG{PIPE} на
DEFAULT
или жеIGNORE
- Убедитесь, что эти 3 действия находятся в пределах их собственной области блока.
2 ответа
write
системный вызов возвращает ошибку EPIPE
в том же случае, когда SIGPIPE
срабатывает, предполагая, что SIGPIPE
не удается убить процесс. Так что лучше всего ставить $SIG{PIPE} = 'IGNORE'
(чтобы не умереть от сигнала), использовать $fh->autoflush
(чтобы избежать буферизации PerlIO, гарантируя, что вы будете немедленно уведомлены о любых ошибках ввода / вывода), и проверить возвращаемое значение print
всякий раз, когда ты это называешь. Если print
возвращает ложь и $!{EPIPE}
установлен, то вы пытались записать в закрытую трубу. Если print
возвращает ложь и $!{EPIPE}
не установлен, у вас есть еще одна проблема для решения.
Похоже, вы не можете сказать. Тем не менее, вы можете обнаружить, что ваша ОС поддерживает SIG_INFO
информация, и если вы можете как-то донести это до Perl, siginfo
структура содержит поле, которое дает номер FD на SIGPIPE
,