2008-09-19 61 views
5

當您管道兩個進程並殺死管道「輸出」處的進程時,第一個進程用於接收「Broken Pipe」信號,這通常會終止它。例如。運行損壞的管道不再結束程序?

$> do_something_intensive | less 

,然後退出用於立即返回到一個負責任的外殼,在SuSE8或以前的版本。 當我想今天,do_something_intensive顯然仍在運行,直到我手動殺死它。看起來有什麼變化(glib?shell?),使程序忽略「破碎的管道」...

你們中的任何一個人對此有提示嗎?如何恢復前者的行爲?爲什麼它被改變了(或爲什麼它總是存在多個語義)?

編輯:進一步測試(使用strace的)揭示了「SIGPIPE」被生成,但該程序不被中斷。當被殺害的簡單

#include <stdio.h> 
int main() 
{ 
    while(1) printf("dumb test\n"); 
    exit(0); 
} 

將繼續與無盡

--- SIGPIPE (Broken pipe) @ 0 (0) --- 
write(1, "dumb test\ndumb test\ndumb test\ndu"..., 1024) = -1 EPIPE (Broken pipe) 

。我可以肯定的程序在我的程序,並確保它終止的信號處理程序,但我更想找一些環境變量,或將迫使程序對SIGPIPE終止

編輯再次外殼選項:它似乎是一個特定於tcsh的問題(bash可以正確處理它)和終端依賴(Eterm 0.9.4)

+0

這將有助於瞭解您正在使用的shell,以及關於do_something_intensive實際所做的更具體的內容。另外,「明顯仍在運行」是什麼意思?它顯示在ps列表中,還是該shell沒有響應?隨意編輯您的問題更多的細節! – ehdr 2008-09-19 18:33:43

+0

它顯示在一個PS列表中,sheel不響應,直到我用CTRL + C終止整個鏈,並且CPU使用率在gkrellm中變高。正在使用的shell是tcsh,正如現在在更詳細的問題中提到的那樣。謝謝你的評論。 – PypeBros 2008-09-23 08:20:28

回答

0

感謝您的建議,解決方案也越來越近......

根據tcsh中的聯機幫助,「非登錄shell繼承父母的終止行爲。其它信號具有殼繼承的值來自其母公司「。

哪個暗示我的終端實際上是問題的根源......如果它忽略了SIGPIPE,那麼shell本身也會忽略SIGPIPE ......

編輯:我有確定的確認,問題只出現在Eterm + tcsh,並在Eterm源代碼中發現一個可疑的丟失信號(SIGPIPE,SIG_DFL)。我認爲結案。

8

那麼,如果在讀取器消失後嘗試寫入管道,則會生成SIGPIPE信號。應用程序有能力捕捉到這個信號,但如果沒有,該進程就會被終止。

在調用進程嘗試寫入之前,不會生成SIGPIPE,因此如果沒有更多的輸出,它將不會生成。

2

根本改變了「做一些密集的事情」嗎?

正如Daniel提到的,SIGPIPE不是一個神奇的「你的管道消失」的信號,而是一個「不錯的嘗試,你不能讀/寫那個管道」信號。

如果你有控制「做一些密集的事情」,你可以改變它寫出一些「進度指示器」輸出,因爲它旋轉。這將及時提升SIGPIPE。

+0

關於do_something_intensive: 如果我在做「是| less」並終止'less',那麼'yes'收到一個SIGPIPE並終止。 如果我正在做「objdump -drS ... | less」,「objdump」繼續(儘管strace顯示重複SIGPIPE);做一個愚蠢的循環做「printf」。 – PypeBros 2008-09-23 08:10:15