【问题标题】:perl filehandle while loop does not terminate on no further linesperl 文件句柄 while 循环不会在没有更多行上终止
【发布时间】:2016-07-13 11:13:47
【问题描述】:

以下设置:

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;

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

但是我无法弄清楚为什么“下一个命令”没有被执行,或者 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

还有很多其他的。

我尝试了 stackoverflow 与“perl while loop close filehandle”的某种组合,但没有成功。

【问题讨论】:

  • 以不同方式重复使用“STREAM”似乎是自找麻烦。
  • 流的结束是如何发出信号的?它是否以文件结尾结束,或者管道是否关闭,或者......?
  • 进程流将通过 sigkill 被杀死,在类似的版本中,通过此时关闭管道来工作。
  • 您显示的 Perl 代码无法编译。例如,stop_stream() { ... } 缺少 sub,并且您使用原型(从来都不是一个好主意)说它需要零参数。而且你没有声明$streampid。请出示您的真实代码
  • 最新编辑显示编译版本。

标签: perl while-loop file-handling


【解决方案1】:

好的,这里问题的根源在于如果文件句柄打开但没有要读取的数据,while ( &lt;FILEHANDLE&gt; ) { 循环将阻塞。

所以/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. 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 2013-04-22
    • 2019-12-12
    • 1970-01-01
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 2016-01-15
    相关资源
    最近更新 更多