Может ли запись в сокет дейтаграммы когда-либо вызывать SIGPIPE?

#c #sockets #posix #datagram #sigpipe

#c #сокеты #posix #дейтаграмма #sigpipe

Вопрос:

Я работаю с некоторым кодом, который должен быть защищен от уничтожения вызывающего абонента из-за SIGPIPE , но единственные выполняемые сокетом записи поступают в сокеты дейтаграмм (как UDP, так и доменные сокеты дейтаграмм Unix). Нужно ли мне беспокоиться о SIGPIPE ? Я использую connect на сокете, но предварительное тестирование (в Linux) показало, что я просто получаю ECONNREFUSED сообщение при отправке, если никто не прослушивает доменный сокет Unix. Не уверен, что происходит с UDP.

Я могу обернуть все это в хаки, чтобы избавиться от SIGPIPE , но если это не проблема, я бы предпочел сэкономить на накладных расходах и снизить сложность кода.

Комментарии:

1. Я собираюсь дать вам плохой ответ. Я думаю, что я видел, как это происходило раньше при запуске приложения во время загрузки системы Linux. Я не могу сказать, был ли это определенно сокет дейтаграммы, который был основной проблемой, но, насколько я знаю, мы не использовали никаких TCP-сокетов для этого приложения. Просто тестовый пример для вас, чтобы рассмотреть, может ли это применяться к вам.

2. Я думаю, я мог бы просто организовать вещи для использования, sendto а не write , чтобы я мог передать этот флаг, который отключает SIGPIPE .

Ответ №1:

Ответ содержится в спецификации для send :

[EPIPE] Сокет закрыт для записи, или сокет находится в режиме подключения и больше не подключен. В последнем случае, и если сокет имеет тип SOCK_STREAM или SOCK_SEQPACKET и флаг MSG_NOSIGNAL не установлен, сигнал SIGPIPE генерируется в вызывающий поток.

http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html

Таким образом, нет, запись в сокеты дейтаграммы не генерирует SIGPIPE или EPIPE ошибку.

Комментарии:

1. Разве в приведенном выше тексте на самом деле не говорится, что вы могли получить это в UDP, если «сокет закрыт для записи» (что бы это ни значило)?

2. @T.E.D.: Возможно (если в сокете дейтаграммы работает функция выключения для записи), но это условие, которое не произошло бы без намерения программиста или ошибки. Это вызвано не одноранговым узлом.

Ответ №2:

Открытая группа — это одно, а Apple — другое. Определенно возможно получить SIGPIPE на iOS при записи в мертвый сокет UDP, как показали некоторые из моих журналов сбоев в последнее время. iOS имеет тенденцию закрывать UDP-сокеты, пока приложение работает в фоновом режиме, запись в эти сокеты может привести к появлению SIGPIPE.
Из моего журнала сбоев (любезно предоставлено testflightapp):

Исключение, последнее появление жертвы
SIGPIPE
2 libsystem_c.dylib 0x32df47ec _sigtramp 48
3 instant talk 0x0005b10e -[IPRSNetDatagramSocket send:size:to:] (iprs_iphone_net.m:671)…

Не припоминаю, чтобы это происходило в Linux, Solaris или Windows — хотя я никогда не пытался закрыть сокет, а затем записать в него.

Комментарии:

1. Закрытие сокета с последующей записью в него не даст SIGPIPE или EPIPE ; это даст EBADF . iOS, должно быть, переводит сокет в какой-то специальный нестандартный режим, чтобы вызвать SIGPIPE . В любом случае мой вопрос был помечен как POSIX, потому что я искал стандартное поведение, но ваш ответ тоже информативен.

Ответ №3:

Согласно man 2 write в моем окне Debian,

EPIPE: fd подключен к каналу или сокету, конец чтения которого закрыт. Когда это произойдет, процесс записи также получит сигнал SIGPIPE. (Таким образом, возвращаемое значение записи отображается, только если программа перехватывает, блокирует или игнорирует этот сигнал.)

Похоже, что возможно получить SIGPIPE при записи в сокет, но неясно, может ли это произойти конкретно для UDP-сокетов.

Комментарии:

1. Справочная страница для send несколько более конкретна, но она не так ясна, как то, о чем говорит POSIX send ..

2. Действительно, @R… Я поддержал ваш ответ через несколько секунд после того, как вы его опубликовали. Я просто хотел запустить процесс с моим сообщением.