为什么不在报警信号处理程序中死掉进程?

时间:2012-04-18 07:13:13

标签: perl die

从如何为Perl系统调用指定超时限制?

eval { 
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required 
    alarm $timeout; 
    $nread = sysread SOCKET, $buffer, $size; 
    alarm 0; 
}; 
if ($@) { 
    die unless $@ eq "alarm\n";   # propagate unexpected errors 
    # timed out 
} 
else { 
    # didn't 
} 

如果发生超时,sub { die "alarm\n" };应该导致进程结束。我想我无法理解die。这个http://www.cs.cf.ac.uk/Dave/PERL/node111.html表示“die()函数用于退出脚本并显示一条消息供用户阅读”。但是,对于上面的脚本,脚本将处理#timed out中的代码。 sysread继续工作。我有一个睡眠时间为30秒的perl脚本,而不是sysread。我的超时设置为10秒。正如预期的那样,执行#timed out中的代码,但脚本继续睡眠。任何输入赞赏

4 个答案:

答案 0 :(得分:10)

die不会导致进程结束,它会引发异常。

现在,如果没有任何异常捕获异常,那么就会结束一个进程,但是你已经code来捕获这个异常。

该过程不会因为您明确阻止其结束而结束。


由于您不清楚自己的行为是什么,可能还有另一种可能性:您使用的是Perl的Windows版本。

alarm是一个Unix系统调用。它的目的(在经过一定时间后发送信号)在Windows上没有任何意义,因为Windows没有信号。

Perl在某种程度上模仿alarm,但只是以非常有限的方式。 sleep很可能是唯一可以被alarm中断的操作。否则,仅在语句之间检查超时。

因此它不会中断sysread,但一旦sysread返回,Perl就会注意到超时到期并模拟信号。

答案 1 :(得分:1)

来自男子警报

   alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds.

sigalarm 发送之前,执行到达else块。在 sysread 之前插入 STDIN ,以便 sigalarm 触发预期结果。

答案 2 :(得分:1)

  

"而不是sysread,我有一个睡眠时间为30秒的perl脚本。我的   超时设置为10秒。正如所料,#timmed中的代码是   执行但脚本继续睡觉。"

真的?

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

eval {
    open my $fh, '<', $0 || die;
    local $SIG{ALRM} = sub {
        print STDERR "hello!\n";
        die "bye!";
    };
    alarm 3;
    while (<$fh>) {
        print $_;
        sleep 1;
    }
    close $fh;
};

if ($@) {
    print "HERE: $@\n";
}

输出:

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
hello!
HERE: bye! at ./test.pl line 9, <$fh> line 3.

超过预期的3秒;如果我只是使用&#34;睡眠100&#34;而不是文件读取。请注意,如果您生成子进程,警报将不会终止该进程,并且父进程必须等待。在那种情况下,&#34;你好!&#34;当警报触发时,信号处理程序中将出现,但是在子进程执行之前,捕获骰子的eval将不会完成。

答案 3 :(得分:0)

将Linux Perl脚本移植到Windows时遇到了同样的问题。

我解决了......

创建非阻塞套接字

$recsock = IO::Socket::INET->new(
                             LocalPort => 68,
                             Proto => "udp",
                             Broadcast => 1,
                            Blocking => 0,
                             ) or die "socket: $@";

将$ continue变量添加到超时句柄

# Timeout handle
$SIG{ALRM} = sub { 
    print "timeout\n";
    $continue = 1;
};

并在超时发生时检查$ continue是否为真:

    alarm($timeout);
     while(1){
         $recsock->recv($newmsg, 1024);
         eval {
            $packet = Net::Package->new($newmsg); 
             ...
        };
        sleep 0.1;
        last if ($continue);
    }
    alarm(0);