perl filehandle while 循环不会在没有更多行时终止

perl filehandle while loop does not terminate on no further lines

以下设置:

linux debian based 4.4.14-v7+ armv7l GNU/Linux
perl version is v5.20.2 built for arm-linux-gnueabihf-thread-multi-64int

一个应该读取数据流的 Perl 脚本(十六进制字符,每行不同长度) 示例流输出:

00 AA BB 11 22 33 44 ...
00 AB BB 11 22 33 44 ...

根据特定值,脚本应执行特定操作。 工作正常但是当流停止发送数据时,即流完成发送数据时,while 循环不会停止。并且脚本等待更多行。

流本身发送 f.e。 5 秒的数据,然后分析脚本应该 do_stuff;

一旦分析脚本完成计算,它将再次启动流。

但是我无法弄清楚为什么 "next command" 没有被执行,或者 while 循环没有在更多行上正确终止。

如果我再次手动启动流处理,分析脚本会继续正常运行,直到不再有更多的行。

简化代码

#!/usr/bin/perl
#script to analyse data
use warnings;
use strict;
use POSIX ();

sub stop_stream($){
  my $pid = shift;
  my $cmd = "/bin/kill -9 $pid";
  system($cmd);
}

while (1){

my $steampid = open( STREAM, "/usr/local/bin/stream |" );

STREAM: while ( my $row = <STREAM> ) {
chomp $row;
my @o = split /\s+/, $row;

#do_stuff;
#..
#this is the row on which the script hangs until it get's new lines in the filehandle.
next STREAM if $o[1] ne "AA";
#...
#do_other_stuff;
#...
}

stop_stream( $steampid );
close STREAM;

}

我试图找出问题的资源:

http://perldoc.perl.org/perlsyn.html#Compound-Statements

http://www.perlmonks.org/?node_id=1065701

和许多其他人。

我尝试将 Whosebug 与 "perl while loop close filehandle" 的某种组合结合使用,但没有成功。

OK,问题的根源在于,如果文件句柄是open,但没有数据可读,while ( <FILEHANDLE> ) {循环会阻塞。

因此 /usr/local/bin/stream 可能会继续传输数据直到被杀死 - 因此您的读取会阻塞。

简单的解决方案是使用类似 IO::Select 的东西,其中有 can_read 作为选项:

use IO::Select;
open ( my $stream, '-|', '/usr/local/bin/stream' ) or die $!; 
#register this filehandle with a new select object
my $select = IO::Select -> new ( $stream );

#2s stream timeout. 
#works because can_read returns a list of filehandles ready for reading
#with only one filehandle registered, it can be used as a simple logic test. 
while ( $select -> can_read(2) ) { 
    my $row = <$stream>; 
    #etc. 
}

#etc.