Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 为什么';是否在报警信号处理器中死亡?是否终止进程?_Perl_Die - Fatal编程技术网

Perl 为什么';是否在报警信号处理器中死亡?是否终止进程?

Perl 为什么';是否在报警信号处理器中死亡?是否终止进程?,perl,die,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

如何为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
。这表示“die()函数用于退出脚本并显示一条消息供用户阅读”。但是,对于上面的脚本,脚本将在#超时时处理代码。sysread也继续工作。我没有使用sysread,而是使用了一个休眠30秒的perl脚本。我的超时设置为10秒。正如预期的那样,执行了#中的代码超时,但脚本继续休眠。从人工报警

   alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds.
sigalarm交付之前,执行到达else块。在sysread之前插入STDIN,以便sigalarm触发预期结果

“我使用的不是sysread,而是一个休眠30秒的perl脚本 超时设置为10秒。正如预期的那样,#中的代码超时 已执行,但脚本继续休眠。”

真的吗

#!/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
严格使用;
使用致命警告=>qw(全部);
评估{
打开我的$fh,“不会导致进程结束,它会引发异常

现在,如果没有任何东西捕捉到异常,那么流程就结束了,但是您已经准备好捕捉这个异常了

进程不会结束,因为您明确阻止它结束


由于您不太清楚自己的行为是什么,因此可能存在另一种可能性:您使用的是Windows版本的Perl

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

Perl在某种程度上模拟了
报警
,但只以非常有限的方式进行模拟。
睡眠
很可能是唯一可被
报警
中断的操作。否则,超时只会在语句之间进行检查


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

将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是否为true:

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

@doon,添加了备选答案。谢谢。我正在使用UNIX版本的perl。谢谢你让我知道die是个例外。我没有意识到that@doon相反,有。但通常您希望
die
,因为它允许人们根据自己的选择处理错误。@doon,还请注意,SIGALRM通常会终止您的进程,因此您的scr如果不使用
local$SIG{ALRM}
,则ipt将强制存在
允许您的析构函数运行。谢谢。这很有用。您在报警后编写的代码(即睡眠例程)与我编写的代码相同。但它是在一个单独的脚本中。感谢您的注释,在命令完成之前,eval将不会完成。尽管这很混乱。如果在其内部包含eval的父进程脚本完成,然后eval必须完成。我希望您理解我的查询。注释框不允许我直观地解释。再次感谢您,如果您将
open$0
替换为
open my$fh',-|',“sleep 10'| | die;
您就会明白我所说的必须等待子进程(shell睡眠)的意思了.但除此之外,正常命令不应阻止报警。
    alarm($timeout);
     while(1){
         $recsock->recv($newmsg, 1024);
         eval {
            $packet = Net::Package->new($newmsg); 
             ...
        };
        sleep 0.1;
        last if ($continue);
    }
    alarm(0);