2011-07-26 63 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