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 положительным или нет в программе. Внешне вы должны проверить, что вы отправляете указатель на действительный сокет