2011-10-14 61 views
3

我正在處理一個任務,涉及編寫程序來處理數據(計算pi)使用叉(進程),信號和選擇。使用信號和sigpipe

我正在處理信號,我想我要做的就是使用SIGPIPE,所以如果程序捕獲它,它會嘗試再次寫入管道(如果一個進程試圖寫入管道沒有讀者,它會發送SIGPIPE)。

我在main()中使用fork()通過將每個進程發送給worker函數來爲每個進程分配相同的工作。

void worker(int id) { 
    .... (this piece of code is not relevant) 

    if(write(pfd[id][1], &c, sizeof(c)) == -1) 
     printf("Error occurred: %s\n",strerror(errno)); 

} 

我如何能實現信號在該功能捕捉SIGPIPE,並把它寫入管道再次?

謝謝!

+0

你應該回去接受你提出的問題的答案。人們不可能回答你的問題,因爲你不接受他們的答案。 –

+0

哦對不起!我會去做。編輯:完成!我是新來這個網站,它是如何工作,但我現在得到它:) – andrepcg

回答

9

通常,而不是捕獲SIGPIPE忽略它,這會導致writeEPIPE一起失敗,而不是以靜默方式終止您的程序。

但是:如果您在寫入管道時遇到了SIGPIPE,請不要再嘗試。它永遠不會工作。 SIGPIPE意味着管道沒有讀卡器 - 如果管道現在沒有讀卡器,它將永遠不會有讀卡器。 (想想這樣:沒有閱讀器的管道將如何得到一個?這是不可能的!)

你的問題是,你正在關閉管道的另一端。解決這個問題,不用擔心SIGPIPESIGPIPE只是症狀。

編輯:這裏有兩個問題需要回答。如果您不能回答這兩個這些問題,那麼請不要打擾處理SIGPIPE

  1. 什麼會導致我的程序來接收SIGPIPE接受SIGPIPE的唯一方法是讓管道的閱讀結束。如果讀取過程崩潰,或者編程爲關閉管道,則會發生這種情況。如果您正在編寫網絡服務器,或者與未知進程通信,這可能很常見。但是,如果你編寫兩個程序,都在本地運行,那麼它可能表示編程錯誤。

  2. 當我的程序捕獲到SIGPIPE時,我的程序會做什麼?如果您正在編寫使用管道與服務器通信的客戶端進程,那麼您應該怎麼處理SIGPIPE?您不能再試一次,並且客戶端通常無法重新啓動他們連接的服務器。只要做明智的,默認的事情,並讓SIGPIPE終止你的程序。但是,如果服務器正在將數據發送到它控制的客戶端並獲得SIGPIPE,那麼可能會重新啓動客戶端。但是這可能是一個非常糟糕的主意 - 例如,如果客戶端是確定性的,它將會再次崩潰,最終會導致無限循環而不是簡單的崩潰。

所以這裏的一般準則是:「只有抓住你準備來處理錯誤。」不要捕捉錯誤只是爲了完整起見。只要讓他們崩潰你的程序,或者導致操作失敗,以後可以返回並調試它。

代碼片段:這是我的一個項目的代碼片段。如果你運行它,SIGPIPE不會終止你的過程。相反,write將生成EPIPE錯誤。如果您正在編寫網絡服務器,則EPIPE是客戶端可能突然斷開連接的一種可能方式。

void 
ignore_sigpipe(void) 
{ 
    struct sigaction act; 
    int r; 
    memset(&act, 0, sizeof(act)); 
    act.sa_handler = SIG_IGN; 
    act.sa_flags = SA_RESTART; 
    r = sigaction(SIGPIPE, &act, NULL); 
    if (r) 
     err(1, "sigaction"); 
} 
+0

我的程序工作正常,我沒有得到任何錯誤(甚至沒有SIGPIPE)。我在想「如果我得到SIGPIPE」 – andrepcg

+0

如果你沒有獲得SIGPIPE,那你爲什麼需要處理它? –

+0

我不知道,但如果該程序將分配給很多計算機,其中一個獲得SIGPIPE,我將通過防止這些情況成爲一名優秀的程序員。那就是我所想的。如果我不對,那麼告訴我:) – andrepcg