Linux下忽略訊號SIGPIPE的方法
阿新 • • 發佈:2019-02-13
最近為測試自己寫的伺服器,臨時寫了一個客戶端,總是發現客戶端收到SIGPIPE的訊號,然後程序退出。
為了客戶端程序收到SIGPIPE不退出,我打算忽略該訊號,下面是我用過的方法:
(1)間接忽略
static void SignalHandler(int nSigno) { signal(nSigno, SignalHandler); switch(nSigno) { case SIGPIPE: printf("Process will not exit\n"); break; default: printf("%d signal unregister\n", nSigno); break; } } atic void InitSignalHandler() { signal(SIGPIPE , &SignalHandler); } int main() { InitSignalHandler(); ........ return 0; }
(2)直接忽略
signal(SIGPIPE,SIG_IGN);
(3)過載signaction
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &sa, 0 );
(1)(2)(3)都不能夠忽略,客戶端收到SIGPIPE之後依然程序退出。
於是乎,查SIGPIPE這個訊號的特性:
如果在寫到管道時讀程序已終止,則產生此訊號。當型別為SOCK_STREAM的套接字已不再連線時,程序寫到該套接字也產生此訊號。
——《UNIX環境高階程式設計》中10.2節
由於我的客戶端是用send()進行傳送資料的,通過man手冊檢視send()函式,看到有一條這樣說:
MSG_NOSIGNAL
Requests not to send SIGPIPE on errors on stream oriented sockets when the other end breaks the connection. The EPIPE error is still returned.
於是將send()最後一個引數flags改為MSG_NOSIGNAL,再次啟動客戶端測試。SIGPIPE被忽略,客戶端沒有因為該訊號退出。
將這次經歷記錄下來,與看到的人共享。