SIGPIPE (OSX) и отключенные розетки?

Я работаю над приложением, которое подключается к серверу через TCP.

Если сокет по какой-либо причине закрыт, я попадаю в обработчик SIGPIPE.

Что мне делать, чтобы recv и send просто возвращали ошибку на отключенном / закрытом сокете?

Спасибо

6 ответов

Я обнаружил, что игнорирование SIGPIPE неэффективно в OS X. Вместо этого используйте SO_NOSIGPIPE. Обратите внимание, что это устанавливается в сокет один раз, в отличие от MSG_NOSIGNAL, который запрашивается при каждом вызове send().

int socket = accept (...); /* (or however you're getting the socket) */
int option_value = 1; /* Set NOSIGPIPE to ON */
if (setsockopt (socket, SOL_SOCKET, SO_NOSIGPIPE, &option_value, sizeof (option_value)) < 0) {
    perror ("setsockopt(,,SO_NOSIGPIPE)");
}

SIG_IGN сигнал, а не обрабатывать его. send вернет -1 и errno будет установлен в EPIPE.

Чтобы игнорировать сигнал, установите обработчик сигнала в SIG_IGN делать это:

struct sigaction sa;
memset(&sa, 0, sizeof(sa));

sa.sa_handler = SIG_IGN;

if (-1 == sigaction(SIGPIPE, &sa, NULL))
{
  perror("sigaction() failed");
}

Игнорирование SIGPIPE, как описано в других ответах (т.е. signal(SIGPIPE, SIG_IGN);) работал для меня на OS X. Также не забудьте протестировать вне отладчика, как сказано в этом комментарии. Я отлаживал с lldb и его обработка сигнала заканчивала мою программу SIGPIPE, хотя я игнорировал этот сигнал. Тестирование вне lldb работал нормально.

Вы можете игнорировать SIGPIPE

 #include <signal.h>

signal(SIGPIPE, SIG_IGN);

Или вы можете использовать обработчик сигнала.

signal(SIGPIPE, handler);
void handler(int signal)
{   
    //("Signal caught");

}

Используйте обработчик сигнала или игнорируйте его

#include <signal.h>
signal(SIGPIPE, SIG_IGN);

во время записи в сокет сначала проверьте, является ли сокет fd положительным или нет в программе. Внешне вы должны проверить, что вы отправляете указатель на действительный сокет

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