SIGPIPE, Сломанная труба
Я работаю над сетевой программой, использующей epoll на Linux-машине, и я получил сообщение об ошибке из gdb.
Program received signal SIGPIPE, Broken pipe.
[Switching to Thread 0x7ffff609a700 (LWP 19788)]
0x00007ffff7bcdb2d in write () from /lib/libpthread.so.0
(gdb)
(gdb) backtrace
#0 0x00007ffff7bcdb2d in write () from /lib/libpthread.so.0
#1 0x0000000000416bc8 in WorkHandler::workLoop() ()
#2 0x0000000000416920 in WorkHandler::runWorkThread(void*) ()
#3 0x00007ffff7bc6971 in start_thread () from /lib/libpthread.so.0
#4 0x00007ffff718392d in clone () from /lib/libc.so.6
#5 0x0000000000000000 in ?? ()
Мой сервер делает n ^ 2 расчет времени, и я попытался запустить сервер с 500 подключенными пользователями. Что может вызвать эту ошибку? и как это исправить?
while(1){
if(remainLength >= MAX_LENGTH)
currentSentLength = write(client->getFd(), sBuffer, MAX_LENGTH);
else
currentSentLength = write(client->getFd(), sBuffer, remainLength);
if(currentSentLength == -1){
log("WorkHandler::workLoop, connection has been lost \n");
break;
}
sBuffer += currentSentLength;
remainLength -= currentSentLength;
if(remainLength == 0)
break;
}
Ответы
Ответ 1
Когда вы пишете на трубку, которая была закрыта (удаленным концом), ваша программа получит этот сигнал. Для простых программ фильтрации командной строки это часто является подходящим действием по умолчанию, поскольку обработчик по умолчанию для SIGPIPE завершает работу программы.
Для многопоточной программы правильное действие обычно игнорирует сигнал SIGPIPE, поэтому запись в закрытый сокет не приведет к завершению работы программы.
Обратите внимание, что вы не можете успешно выполнить проверку перед записью, так как удаленный конец может закрыть сокет между вашей проверкой и вашим вызовом до write()
.
См. этот вопрос для получения дополнительной информации об игнорировании SIGPIPE: Как предотвратить SIGPIPE (или обрабатывать их правильно)
Ответ 2
Вы не поймаете SIGPIPE
сигналы, но вы пытаетесь записать в трубу, которая была сломана/закрыта.
Довольно понятно.
Обычно достаточно обрабатывать сигналы SIGPIPE
как no-op и обрабатывать случай ошибки вокруг вашего вызова write
любым способом, который вам нужен... например это.