2009-11-17 422 views
1

我有一個Perl腳本,它執行fork/exec來在後臺啓動另一個工具並監視某些文件系統更改這個其他工具正在運行。這似乎像預期的那樣工作。Perl Script,Fork/Exec,System聲明我的進程已經死亡,但實際上只有我的子進程已經死亡

當我從shell(例如Bash)啓動這個Perl腳本時,只要我的Perl腳本正在運行,shell提示應該消失。它將繼續運行,直到預期的文件修改發生;但不能保證文件修改可能由外部工具完成,在這種情況下,外部工具將退出,但我的腳本將繼續運行,並且必須以某種方式處理該情況 - 這種處理超出了問題的範圍,並且與我的問題沒有關係(到目前爲止它甚至沒有實施)。

我的問題是,只要我的子進程死了,Bash就會返回到它的提示符,聲稱我的進程已經完成運行......這是不正確的。它顯然仍在後臺運行,並且仍在等待文件系統修改。如果我繼續在腳本的主循環中打印一些文本,即使bash已經返回到提示符,仍然會打印此文本。

我不明白是什麼讓bash相信我的流程已經退出。我嘗試在腳本中阻止SIGCHLD信號,我嘗試關閉和/或重定向STDOUT/STDERR/STDIN(它們在叉上覆制,但你永遠不知道) - 沒有成功。我甚至嘗試着名的「雙叉」,使最終的孩子獨立於我的腳本過程,獲得相同的結果。無論我做什麼,只要我的孩子(或孫子)死亡,Bash就會認爲我的過程已經退出。在後臺啓動我的腳本(在末尾使用「&」)使得Bash甚至告訴我XYZ過程已經完成(並且它在這裏命名我的過程,而不是子進程,儘管我的進程很快活着並且通過終端打印STDOUT那一刻)。

如果這只是Bash的一個問題,我不會在意,但其他第三方應該運行我的腳本的軟件的行爲方式也是一樣的。一旦我的孩子死亡,他們聲稱我的劇本事實上已經死亡,這根本不是事實。

+2

我認爲,而不是這個散文描述,它會更有幫助的,而不是你的代碼減少到最小的可能的大小,說明你的問題,並張貼。如果在這個過程中你的問題消失了,你已經獲得了有用的調試信息。 – 2009-11-17 19:04:44

+0

同意亞當。讓我看看代碼! (對Jerry Maguire道歉) – 2009-11-17 19:08:41

+0

對不起,沒有發佈任何代碼,在嘗試找到這個問題的原因約30分鐘後,我還剩下10分鐘才離開(否則我會錯過一次重要的約會) - 上面的描述是我能在10分鐘內得出的最好的結果(將代碼剝離到最小的測試用例需要更多的時間)。我從現在開始的11個小時內再次訪問代碼;那麼我會看看我能做些什麼關於代碼示例。 – Mecki 2009-11-17 22:08:56

回答

1

只是一個健全的檢查,是你的主要程序走右叉?它應該遵循非零路徑:

my $pid = fork; 
if ($pid == 0) { 
    print "Child\n"; 
} else { 
    print "Main\n"; 
} 

man fork

成功完成後,叉() 值0返回到子 過程並返回 進程ID子進程向父進程 進程。

+0

嗯......好點你在那裏...我會仔細檢查,在從現在開始的11個小時內(這是當我將再次訪問我的代碼)。這確實是一個愚蠢的錯誤,但每個人偶爾會犯一些愚蠢的錯誤,如果它是在錯誤的分支中執行exec,這確實會符合上述不希望的行爲。 – Mecki 2009-11-17 22:04:32

+0

你是對的 - 在exec顯示exec運行在父進程而不是在子進程之前打印一些調試輸出 - DOOHH!愚蠢的錯誤! – Mecki 2009-11-18 09:16:03