2011-09-11 10 views
2

私が 'open(A、 "proc |")を実行すると、 ) '' proc 'がstdoutへの書き込みを完了していなくても、即座に を返しますか?Perl: 'open(A、 "proc |")'を実行するとすぐに閉じる

は「perlfuncの男が」私に語った:

が途中で配信される SIGPIPEになります(すなわち、それを閉じたもう一方の端でそれに書き込むプロセス 前に)パイプの読み出し側を閉じますライターに。他端が を処理できない場合は、パイプを閉じる前にすべてのデータを確実に読み取るようにしてください。

回避方法がありますか?具体例としては、上記 コードを印刷 "LOOPのEXIT"、決して "CLOSED":

$|=1; 
open(A,"curl -sN http://test.barrycarter.info/bc-slow-cgi.pl|"); 

while (<A>) { 
    print "THUNK: $_\n"; 
    if (/5$/) {last;} 
} 

print "LOOP EXIT\n"; 
close(A); 
print "A CLOSED\n"; 

bc-slow-cgi.plだけで永遠に毎秒一回の時間を()出力します。

+0

ここで完璧に機能します。 –

+3

どのバージョンのperlとcurlがありますか?あなたのコードはperl 5.10.1とcurl 7.21.3で期待どおりに動作します。クイックグーグルでは、SIGPIPE –

+0

perl v5.10.0とcurl 7.19.7で終了しない古いバージョンのカールにいくつかのバグがあったことを示しています。私はアップグレードしようとしていましたが、カールしていないプログラムでも動作するので、@ ikegamiのソリューションはより好きです – barrycarter

答えて

5

closeハンドルによって作成されるopen -|子が終了するのを待ちます。 closeに電話した後に次回書き込みをしようとすると、PIPE信号またはエラーで子供が死ぬはずですが、その時間を待たずに子供を殺すことができます。

my $pid = open(...); 

while (...) { 
    ... 
} 

kill PIPE => $pid; 
close(...); 

PIPEは少し正統ですが、ここでは適切と思われました。 TERMなどをお気軽にお送りください。