自Perl 5.10.1以来,这可以正常工作:陷入了SIGINT。
#!/usr/bin/perl
use strict;
use warnings;
$SIG{INT} = sub { die "Caught a sigint $!" };
sleep(20);
但是这里的SIGINTs 不 陷入困境。
#!/usr/bin/perl
use strict;
use warnings;
$SIG{INT} = sub { die "Caught a sigint $!" };
END {
sleep(20);
}
这可以通过在END
块中再次设置处理程序来解决,如下所示:
END {
$SIG{INT} = sub { die "Caught a sigint $!" };
sleep(20);
}
但如果您有多个块,则无效:必须为每个块再次设置处理程序。
我试图解决这个问题,我无法在perldoc找到解释。我能找到的这种行为的唯一提及是来自Practical Perl Programming A D Marshall 1999-2005
的脚注注意发送到脚本的信号可以绕过END块。
有人会解释这个吗?
答案 0 :(得分:3)
这对我有用:在首先运行的 END块中重新安装处理程序(代码中的最后一个)。
use warnings;
use strict;
use feature 'say';
$SIG{INT} = sub { say "SIGINT: got zap!" };
#sleep 10;
say "done";
END { say "END, runs last" }
END { say "END, runs next to last. Sleep then print"; sleep 10; say "Woke up."; }
# Executed first in END phase. The sole purpose: to reinstall the handler
END {
$SIG{INT} = sub { say "SIGINT in END block, got zap" };
}
几秒钟后启动并按Ctrl-C-ed打印
done. END, runs next to last. Sleep then print ^CSIGINT in END block, got zap Woke up. END, runs last
因此,您需要在代码中添加END
块,,END { $SIG{INT} = 'IGNORE' }
。
似乎更改为" END" ${^GLOBAL_PHASE}
删除或以其他方式禁用处理程序。
但是,一旦处理程序在END
阶段重新安装,它就会始终有效。当然,在首先执行的END
块中这样做是最干净的。
我会更新(如果)我了解更多细节并找到有关此行为的文档。
答案 1 :(得分:1)
"结束"代码块尽可能晚地执行 ,即
perl
之后 已经完成了程序的运行,就在 解释器出现之前 退出 ,即使它因die()
函数而退出。 (但不是 它会通过"exec
"变成另一个程序,或被吹出 通过信号浇水 - 你必须自己陷阱(如果可以的话)。)
我希望在退出解释器之前删除信号处理程序。因此,我无法看到令人惊讶或意料之外的事情。