2016-07-16 16 views
1

從FreeBSD上我打開幾個子進程與IPC::Open2::open2(),傳遞給每一個進程中的「參數」,通過它的標準輸入一個Perl腳本(也許我應該關閉後,這個標準輸入),也是我做的事:Perl open2()與SIGCHLD一起死鎖?

sub handle_SIGCHLD { 
    for(;;) { 
    my $kid = waitpid(-1, WNOHANG); 
    break if $kid == 0; 
    my $KidOutputFD = ...; # I stored the kid's output pipe FD earlier in the program 
    my $KidOutput = read_file($KidOutputFD); # use File::Slurp 
    # process $KidOutput 
    } 
}} 

$SIG{'CHLD'} = \&handle_SIGCHLD; 

現在問題:像這樣的代碼會導致死鎖嗎?我更喜歡讀取孩子的輸出,而不是在它到達時,但是當它終止讀取整個輸出時;可能會導致問題嗎?

此外,我通過stdin傳遞給孩子的「參數」可能是一個很長的字符串。我將通過一個print運算符將整個字符串傳遞給子標準符的FD。在將參數寫入腳本的過程中,它可以阻止嗎?

還有什麼我應該做的,以確保沒有死鎖的?也許我應該處理SIGPIPE? (我不喜歡這樣做,太多的工作簡單,子進程將輸入字符串轉換爲輸出字符串是否有一個更簡單的方法?)

另外請注意,我跨越多個子進程。有時我會等一個進程終止,有時候我會用SIGTERM殺死一個子進程。


更具體的問題:可以寫入PIPE(這是在兩側打開,並且不會被關閉)塊(如果對方沒有讀它)?

+1

'waitpid'可以返回-1,這樣就可以將這段代碼放入一個無限循環 – mob

回答

0

http://man7.org/linux/man-pages/man7/pipe.7.html(不是FreeBSD,但我認爲這並不重要,畢竟那裏是我們可以改變我們的OS的可能性)。

管容量 的管具有有限的容量。如果管道已滿,則寫入(2)將會阻塞或失敗,具體取決於是否設置了O_NONBLOCK標誌(請參見下文)。

因此得出,子進程可能會「掛起」試圖將數據寫入到我們作爲一個dealock終止時,我們可以無限地等待。

1

五月寫入PIPE(這是在兩側打開,並且不會被關閉)塊(如果對方沒有讀它)?

絕對是。管道的容量有限,如果管道已滿,寫入管道將會阻塞。

例如,以下可能發生在孩子:

  1. 寫到stdout
  2. 寫到stdout
  3. ...
  4. 寫到stdout
  5. 試圖寫入STDOUT ,但管道已滿,因此它會阻塞,直到管道被清空。

如果發生這種情況,孩子會無限期因爲家長不從管道中讀取,直到孩子退出阻塞(因此永遠不會退出)。這在技術上並不是deadlock,因爲家長仍然可以隨心所欲地做任何事情,但這絕對是一個問題。

注意:如果孩子使句柄非阻塞,寫入將失敗而不是阻塞。