Вопрос
Можно ли отключить повышение сигнала (SIGPIPE
) при записи в pipe()
FD, без установки моего собственного обработчика сигналов или отключения / маскирования сигнала глобально?
Фон
Я работаю над небольшой библиотекой, которая иногда создает канал и fork()
s временный дочерний / фиктивный процесс, который ожидает сообщения от родителя. Когда дочерний процесс получает сообщение от родителя, он умирает (намеренно).
Проблема
Дочерний процесс по независящим от меня обстоятельствам запускает код из другой (сторонней) библиотеки, которая подвержена сбоям, поэтому я не всегда могу быть уверен, что дочерний процесс жив, прежде чем я write()
подключусь к конвейеру.
Это приводит к тому, что я иногда пытаюсь write()
подключиться к каналу с уже мертвым / закрытым концом дочернего процесса, и это вызывает SIGPIPE
в родительском процессе. Я нахожусь в библиотеке, которую будут использовать другие клиенты, поэтому моя библиотека должна быть как можно более автономной и прозрачной для вызывающего приложения. Установка специального обработчика сигналов может нарушить код клиента.
Пока работаю
Я решил эту проблему с сокетами, используя setsockopt(..., MSG_NOSIGNAL)
, но я не могу найти ничего функционально эквивалентного для каналов. Я рассмотрел вопрос о временной установке обработчика сигналов, чтобы поймать SIGPIPE
, но я не вижу способа ограничить его область действия вызывающей функцией в моей библиотеке, а не всем процессом (и это не атомарно).
Я также нашел здесь аналогичный вопрос, касающийся SO, который запрашивает то же самое, но, к сожалению, использование _9 _ / _ 10_ не будет атомарным, и существует удаленная (но возможная) вероятность того, что дочерний процесс умрет между моими select()
и write()
вызовами.
Вопрос (сокращение)
Есть ли способ выполнить то, что я пытаюсь здесь сделать, или выполнить атомарную проверку и запись в канал, не вызывая поведения, которое будет генерировать SIGPIPE
? Кроме того, можно ли добиться этого и узнать, произошел ли сбой дочернего процесса? Знание того, произошел ли сбой, позволяет мне обосновать предложение поставщика, предоставившего аварийную библиотеку, и позволяет им узнать, как часто происходит сбой.
SIGPIPE
вSIG_IGN
. - person EOF   schedule 16.12.2016setsockopt()
. И я думаю, что полученный код будет проще и легче поддерживать, сохраняя при этом функциональность. - person Iharob Al Asimi   schedule 16.12.2016sigaction()
, чтобы (атомарно AFAIK) изменить старый обработчик сигналов на новый, который улавливаетSIGPIPE
. Внутри обработчика проверьте, является ли ответственный канал тем, который был создан вашей библиотекой. Если да, войдите. В противном случае верните обработчик сигнала к старомуraise(SIGPIPE);
. - person EOF   schedule 16.12.2016sigaction()
перед моимwrite()
вызовом, проверить, что PID отправителя является моим собственным черезgetpid()
, а затем проверить, совпадает лиFD
в вопросеsa.si_fd
с записью моего канала FD? - person Cloud   schedule 16.12.2016SIGPIPE
передread()
в вашем потоке. OTOH, я не думаю, чтоSIGPIPE
хоть сколько-нибудь близко к этому популярному. - person EOF   schedule 16.12.2016MSG_NOSIGNAL
, чтобы избежать повышенияSIGPIPE
. Это стандартизировано в POSIX.1-2008, поэтому оно также переносимо. - person Nominal Animal   schedule 16.12.2016si_fd
не является членомsiginfo_t
, предписанного POSIX. - person Jonathan Leffler   schedule 16.12.2016