2011-07-26 35 views
12

我正在使用epoll在linux机器上的网络程序,我从gdb得到错误信息。SIGPIPE,破管

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; 
     } 
+4

当您尝试写入已关闭的管道时,发生SIGPIPE,请确保您写入的管道未关闭。 –

+0

发布您的代码。 – 2011-07-26 01:23:48

+0

作为答案发布,所以我们可以upvote它。这个问题的答案尽可能多,因为问题的信息很少。 @LCYSoft:GDB跟踪在没有调用函数的代码时是没用的。 –

回答

24

当您向已经关闭(由远端)的管道,你的程序将收到此信号。对于简单的命令行筛选程序,这通常是一个适当的默认操作,因为SIGPIPE的默认处理程序将终止程序。

对于多线程程序,正确的动作通常是忽略这个SIGPIPE信号,这样写入一个封闭的套接字将不会终止程序。

请注意,您无法成功写入之前进行检查,因为远端可以在你的检查和您的来电write()之间关闭套接字。

看到这个问题,关于忽略SIGPIPE的更多信息:How to prevent SIGPIPEs (or handle them properly)

+0

有时你会得到一个SIGPIPE,因为远程端关闭了连接*并且从来没有告诉你。*系统崩溃导致了很多,因为它们没有清理打开的套接字,所以你不知道套接字在你写一些东西给它,而远端没有意识到连接。 –

+2

您可以成功执行检查就好了;你不能这样做。 :) –

+0

@Tomalak Geret'kal不,你不能。除了尝试I/O操作之外,没有Sockets API会告诉您。 – EJP

2

你不要再追SIGPIPE信号,但你要写信给一个已经破碎/关闭的管道。

公平不言自明。

它通常足以处理SIGPIPE信号,无操作和处理周围的write呼叫任何应用程序特定的方式,你需要...错误情况类似this