自 Perl 5.10.1 以来,这按预期工作:SIGINT 被捕获。
#!/usr/bin/perl
use strict;
use warnings;
$SIG{INT} = sub { die "Caught a sigint $!" };
sleep(20);
但这里的信号情报没有被困。
#!/usr/bin/perl
use strict;
use warnings;
$SIG{INT} = sub { die "Caught a sigint $!" };
END {
sleep(20);
}
这可以通过在 END
block 中再次设置处理程序来解决,如下所示:
END {
$SIG{INT} = sub { die "Caught a sigint $!" };
sleep(20);
}
但如果您有多个 block ,那将不起作用:必须为每个 block 重新设置处理程序。
我试图解决这个问题,但在 perldoc 找不到解释。 .我能找到的唯一提及此行为的脚注来自 Practical Perl Programming A D Marshall 1999-2005
Note Signals that are sent to your script can bypass the END blocks.
谁能解释一下?
最佳答案
这对我有用:在最先运行的 END block 中重新安装处理程序(最后在代码中)。
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 键打印
done. END, runs next to last. Sleep then print ^CSIGINT in END block, got zap Woke up. END, runs last
所以你需要添加一个END
block ,在代码的最后,END { $SIG{INT} = 'IGNORE' }
.
似乎对“END”${^GLOBAL_PHASE}
的更改删除或以其他方式禁用了处理程序。
但是一旦处理程序在 END
阶段重新安装,它就始终有效。在最先执行的 END
block 中执行此操作当然是最干净的。
当(如果)我了解更多详细信息并找到有关此行为的文档时,我会更新。
关于Perl 信号处理程序在 END block 中重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40688429/