Межплатформенный (POSIX) аналог для sigtimedwait()

Вариант использования — это необходимость маскировать SIGPIPE в потоках pthread, которые выполняют свои собственные write() и/или SSL_write(), и компилировать их в текущих POSIX-системах, таких как Linux, macOS, BSD и т. д. Типичный подход к Linux объясняется довольно хорошо здесь, и есть много хороших дополнительных обсуждений по теме здесь.

Типичный signal(SIGPIPE, SIG_IGN) работает везде, где я пробовал, но (я считаю) должно быть более хирургическое решение, позволяющее избежать глобального игнорирования SIGPIPE. Также было бы неплохо по возможности избегать прагмы, специфичной для платформы.

Похоже, что функция sigtimedwait() не существует в (текущих?) версиях macOS, поэтому маловероятно, что кросс-платформенное решение использует этот подход.

Кажется, что функция sigwait() существует везде, но она заблокируется навсегда, если конкретный сигнал на самом деле не ожидается. Таким образом, следующий лучший подход, по-видимому, состоит в том, чтобы использовать sigpending() для просмотра того, что ожидается, а затем sigwait() для его обслуживания, которые оба кажутся доступными.

Что меня беспокоит, так это то, что практически ничего (что я могу найти) не написано по этой конкретной проблеме, что обычно является признаком того, что я упускаю что-то болезненно очевидное.

Итак, является ли pthread_sigmask() / sigpending() / sigwait() / pthread_sigmask() хорошим выбором для описанного выше варианта использования? Или есть (не?) очевидные подводные камни, о которых я должен знать?


person Chuck Wolber    schedule 02.08.2020    source источник
comment
Должно быть более хирургическое решение, позволяющее избежать глобального игнорирования SIGPIPE Почему? Если вы правильно обрабатываете ошибки, SIGPIPE в большинстве ситуаций бесполезна. См. Как предотвратить SIGPIPE (или правильно с ними обращаться) и Почему существует SIGPIPE?   -  person Andrew Henle    schedule 03.08.2020
comment
Почему бы просто не обработать сигнал? Пусть обработчик установит флаг возникновения sigpipe и выйдет. Проверьте флаг позже.   -  person n. 1.8e9-where's-my-share m.    schedule 03.08.2020
comment
@n.'местоимения'm. - Я подозреваю, что вы имеете в виду использование sigaction(). Эта функция предназначена для каждого процесса, а не для потока. Я надеялся на более хирургический подход, который позволил бы мне абстрагировать поведение в библиотеку, которая имела бы как можно меньше глобальных эффектов.   -  person Chuck Wolber    schedule 03.08.2020
comment
@AndrewHenle - на данный момент я склоняюсь к этому. Вы правы в том, что от SIGPIPE мало пользы, если вы выполняете правильную проверку возврата. И все же я все еще удивлен тем, насколько ограничены возможности переносимой обработки сигналов для каждого потока; но это другой вопрос, чем тот, который я изначально задал.   -  person Chuck Wolber    schedule 03.08.2020


Ответы (1)


Итак, является ли pthread_sigmask() / sigpending() / sigwait() / pthread_sigmask() хорошим выбором для описанного выше варианта использования? Или есть (не?) очевидные подводные камни, о которых я должен знать?

Дело в том, что sigwait() и sigtimedwait() были выпущены в одной и той же версии POSIX. Если вы хотите добиться переносимости, полагаясь на стандарты, и если macOS не соответствует требованиям, исключая последние, вам следует задуматься о том, как еще она не соответствует. На самом деле, есть другие области несоответствия, которые могут вас укусить, хотя и не обязательно с вашей конкретной предлагаемой серией вызовов функций.

Для лучшей переносимости я бы предложил использовать самые простые решения. В этом случае я бы просто проигнорировал сигнал (то есть установил бы его расположение на SIG_IGN). Я предполагаю, что вы понимаете, что расположение сигналов является характеристиками для каждого процесса, а не для каждого потока, но что с того? Все ваши write() в любом случае должны проверять свои возвращаемые значения, чтобы обнаруживать короткие записи и ошибки, и если они делают это правильно, то они предпримут соответствующие действия без необходимости получать сигнал.

person John Bollinger    schedule 03.08.2020
comment
Я надеялся абстрагироваться чистым способом и избежать глобального поведения, но я согласен с тем, что SIG_IGN, вероятно, является правильным подходом, когда речь идет о поведении SIGPIPE. Я все еще борюсь с общим вопросом переносимой обработки сигналов в приложениях pthread. Возможно, это одна из тех вещей, которые в конечном итоге испаряются при тщательном рассмотрении. - person Chuck Wolber; 03.08.2020
comment
Возможно, стоит отметить, что соответствующий sigpending() не может отличить асинхронный SIGPIPE (в ожидании процесса) и синхронный SIGPIPE (в ожидании вызывающего потока). Таким образом, первоначальная мысль OP не сработает в соответствующей реализации. (Интересно, что OS X выглядит для меня явно несоответствующей: только один из N подходящих потоков будет иметь sigpending() возврат true для асинхронного ожидающего сигнала, хотя любой из этих N может успешно вызвать sigwait().) - person pilcrow; 03.08.2020