Можно ли определить, какую трубу выбросил 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,

Другие вопросы по тегам