2016-01-25 143 views
8

我需要在阻止io的腳本上超時。
令人驚訝的事實證明exit掛起如果有一個開放的管子流程:Perl:關閉信號處理程序中的子進程管道掛起?

#!/usr/bin/perl                        
(-f "foo") || die "file foo doesn't exist"; 
open(IN, "tail -f foo |"); 

$SIG{ALRM} = sub 
{ 
    print "trying to exit...\n"; 
    exit 0;  # Hangs with above open() call 
}; 
alarm 1; 

while (1) 
{ 
    sleep 5; # Do stuff ... 
} 

由於沒有open調用它的作品,可惜刪除它是不是在這種情況下,腳本需要它的選項。

看起來exit試圖關閉文件句柄,這是什麼是懸掛:

$SIG{ALRM} = sub 
{ 
    print "trying to close...\n"; 
    close(IN);   # Hangs ... 
    print "ok\n"; 
    exit 0; 
}; 

我想這不是太高興從一個訊號處理器中收穫着孩子......

不任何人都知道一個很好的解決方法?

回答

10

的信號處理程序是一個紅鯡魚,close會不顧阻止:

open my $foo, "tail -f foo |" or die "Can't open process: $!"; 

close $foo;  # <--- will block 

一種方式來解決這個問題是通過open捕捉子進程ID,然後kill那個孩子:

my $subprocess = open my $foo, "tail -f foo |" or die "Can't open process: $!"; 

say "subprocess=$subprocess"; 

kill 'KILL', $subprocess; 

close $foo;  # <--- happy now 
+1

當然你是對的,傻了!令人困惑的是,一個早期的「出口」實際上是有效的,但僅僅是因爲它造成了一種競爭條件(這個孩子還沒有準備好)。謝謝 ! – lemonsqueeze

1

直接使用POSIX::_exit()就像手冊頁建議似乎解決了這個特定的問題。但是這味道是A-B的問題。您是否確定通過使用比普通管道更高級的處理子流程的方法解決了真正的問題,例如IPC::Run

+0

這也可以工作,但是'tail'進程仍然運行並且變成孤兒... – lemonsqueeze