2

私のパイプ(ファイルハンドル、ソケット)が壊れます(時々)。次のコードで再現できます。

my $counter = 5;
alarm(1);

open(FH,"while(sleep 2); do date; done |") or die $!;
while (<FH>) { print; }
close(FH);

BEGIN {
    $SIG{ALRM} = sub { 
        print "alarm!\n"; 
        exit if --$counter == 0;
        alarm(1);
    };
}

どちらが生成されます:

alarm!
alarm!
Thu Feb  7 11:46:29 EST 2013
alarm!
alarm!
alarm!

このプロセスをstraceすると、生成されたシェルがSIGPIPEを取得することがわかります。ただし、Perlプロセスは問題なく続行されます。これを修正するにはどうすればよいですか?

4

1 に答える 1

2

問題は、<FH>システムコールが中断されたためにfalseが返されることです。これがperlでこれを処理する慣用的な方法であるかどうかはわかりません(そしてより良い答えを見たいと思います)が、以下はうまくいくようです:

my $counter = 5;
alarm 1;

open my $fh, '-|', 'while(sleep 2); do date; done' or die $!;
loop:
while (<$fh>) { print; }
goto loop if $!{EINTR};
close $fh;

BEGIN {
    $SIG{ALRM} = sub { 
        print "alarm!\n"; 
        alarm 1;
        exit if --$counter <= 0;
    };
}
于 2013-02-07T17:28:37.667 に答える