Я работаю над приложением, которое подключается к серверу через TCP.
Если сокет по какой-либо причине закрыт, я попадаю в обработчик SIGPIPE.
Что мне сделать, чтобы recv и send просто возвращали ошибку на отключенном / закрытом сокете?
Спасибо
Я работаю над приложением, которое подключается к серверу через TCP.
Если сокет по какой-либо причине закрыт, я попадаю в обработчик SIGPIPE.
Что мне сделать, чтобы recv и send просто возвращали ошибку на отключенном / закрытом сокете?
Спасибо
Я обнаружил, что игнорирование 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.
read()
и recv()
возвращают 0
, если партнер закрыл или прервал соединение. Подробнее см. man read
или man recv
. Если все еще неясно, задайте еще один вопрос по этой другой теме.
- person alk; 22.10.2013
signal
нестандартна для разных платформ. В Linux вы можете уговорить его вести себя так, как вы хотите, с помощью макросов тестирования функций, но я не знаю, какие настройки OSX установлены по умолчанию. Лучше использовать sigaction
, и я вижу, что alk оставил ответ, описывающий, как это сделать.
- person Duck; 22.10.2013
Чтобы игнорировать сигнал, установите для обработчика сигнала значение 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");
}
printf()
из обработчиков signl, поскольку printf()
не гарантирует безопасность сигналов.
- person alk; 22.10.2013
использовать обработчик сигнала или игнорировать его
#include <signal.h>
signal(SIGPIPE, SIG_IGN);
при записи в сокет сначала проверьте, положительный ли fd сокета в программе. Внешне вы должны проверить, что вы отправляете указатель действительного сокета.
signal()
вам, скорее всего, потребуется повторно применить обработчик после того, как он был однажды использован. Не используйте signal
use sigaction () `.
- person alk; 22.10.2013