Perl 信号处理程序在 END block 中重置

标签 perl signals perl5.10

自 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/

相关文章:

perl - 使用 OpenOffice::OODoc 传输表格样式

python - 当 Popen 终止时我如何接收信号?

perl - 我可以确保在 5.10+ 上编写的 Perl 代码可以在 5.8 上运行吗?

multithreading - 在 Perl 中完成后如何清理线程?

Perl 语法细节 - 列出有或没有括号的上下文?

android - Android中屏幕闪烁的最快方法

perl - 在 Perl 中,一个值可以未初始化但仍被定义吗?

perl - Perl 5.10 是否将原型(prototype)搞砸了?

perl - 让 github 使用 perldoc 显示 readme 文档

linux - 为什么 Linux 在按下 Ctrl+C 时总是输出 "^C"?