为什么不能从Perl的信号处理程序中终止循环?

问题描述:

有没有人可以解释为什么下一个脚本不起作用? Label not found for "last SOME_BLOCK"错误的原因是什么?为什么不能从Perl的信号处理程序中终止循环?

#!/usr/bin/perl 
use v5.14; 
SOME_BLOCK: { 
    alarm 1; 
    $SIG{ALRM} = sub { 
     last SOME_BLOCK; 
    }; 
    my $count = 0; 
    while (1) { 
     $count += 1; 
     say $count; 
    } 
}; 

last经由或next退出子程序根据perldoc禁止(和通常触发警告)。这是因为它非常混乱 - Perl需要动态搜索范围以查找要跳过的块,并调用各种函数的返回值(但应使用什么返回值?)。 return通常更安全。

在信号处理上下文中,这很麻烦,因为Perl实际上必须暂停执行脚本以执行信号处理程序。所以它现在运行两个独立的执行上下文,而信号处理器上下文不能直接影响主要上下文的控制流,这就是为什么你会得到这个错误。

有两件事情可以做:

  • 抛出异常(使用die),并抓住它的外块。这是不可取的,因为它可能会中断任何事情。
  • 设置在信号处理程序外定义的全局标志,例如($caught_signal = 1),并在方便的地方检查内部代码中的内容。
+0

扔'死'不仅是不受欢迎的,这是正常的事情。信号不会中断“几乎任何事情”。由于它们仅在Perl操作符之间进行检查,因此不会在系统调用,库调用或Perl操作中死掉。 – ikegami 2013-02-24 08:22:55

+0

我同意,但它仍然不如检查代码中明确定义的点。 – rjh 2013-02-24 10:46:51