2016-01-25 13 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

関連する問題