为什么不能从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
),并在方便的地方检查内部代码中的内容。
扔'死'不仅是不受欢迎的,这是正常的事情。信号不会中断“几乎任何事情”。由于它们仅在Perl操作符之间进行检查,因此不会在系统调用,库调用或Perl操作中死掉。 – ikegami 2013-02-24 08:22:55
我同意,但它仍然不如检查代码中明确定义的点。 – rjh 2013-02-24 10:46:51