1. 程式人生 > >Linux下忽略訊號SIGPIPE的方法

Linux下忽略訊號SIGPIPE的方法

最近為測試自己寫的伺服器,臨時寫了一個客戶端,總是發現客戶端收到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被忽略,客戶端沒有因為該訊號退出。

將這次經歷記錄下來,與看到的人共享。