Perl 信号处理程序在 END 块中重置 [英] Perl signal handlers are reset in END blocks

查看:42
本文介绍了Perl 信号处理程序在 END 块中重置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自 Perl 5.10.1 起,这按预期工作:SIGINT 被捕获.

#!/usr/bin/perl使用严格;使用警告;$SIG{INT} = sub { die "Caught a sigint $!"};睡眠(20);

但这里的信号情报没有被困.

#!/usr/bin/perl使用严格;使用警告;$SIG{INT} = sub { die "Caught a sigint $!"};结尾 {睡眠(20);}

这可以通过在 END 块中再次设置处理程序来解决,如下所示:

END {$SIG{INT} = sub { die "Caught a sigint $!"};睡眠(20);}

但是如果您有多个块,这将不起作用:必须为每个块再次设置处理程序.

我试图解决这个问题,但在 perldoc.我能找到的唯一提到的这种行为是 Practical Perl Programming AD Marshall 1999-2005

<块引用>

注意发送到脚本的信号可以绕过 END 块.

有人能解释一下吗?

解决方案

这对我有用:在最先运行的 END 块中重新安装处理程序(代码中的最后一个).

使用警告;使用严格;使用功能说";$SIG{INT} = sub { 说SIGINT: got zap!"};#睡眠10;说完成";END { 说END,最后运行"}END { 说END,倒数第二运行.睡眠然后打印";睡10;说醒了";}# 在END阶段首先执行.唯一目的:重新安装处理程序结尾 {$SIG{INT} = sub { 说END 块中的 SIGINT,得到了 zap"};}

启动并在几秒钟后按 Ctrl-C-ed 时打印

<前>完毕.END,倒数第二次运行.睡眠然后打印END 块中的 ^CSIGINT,得到了 zap醒了.END,最后运行

所以你需要添加一个 END 块,在代码的最后END { $SIG{INT} = 'IGNORE' }.

似乎对END"的更改 ${^GLOBAL_PHASE} 删除或以其他方式禁用处理程序.

但是一旦在 END 阶段重新安装处理程序,它就会一直有效.当然,在最先执行的 END 块中这样做是最干净的.

我会在(如果)我了解更多细节并找到有关此行为的文档时进行更新.

This works as expected since Perl 5.10.1: SIGINTs are trapped.

#!/usr/bin/perl

use strict;
use warnings;

$SIG{INT} = sub { die "Caught a sigint $!" };

sleep(20);

But here SIGINTs are not trapped.

#!/usr/bin/perl

use strict;
use warnings;

$SIG{INT} = sub { die "Caught a sigint $!" };

END {    
    sleep(20);
}

This can be fixed by setting the handler again in the END block, like so:

END {
    $SIG{INT} = sub { die "Caught a sigint $!" };

    sleep(20);
}

But that won't work if you have more than one block: handlers must be set again for every block.

I've tried to figure this out and I can't find an explanation at perldoc. The only mention of this behaviour I can find is a footnote from Practical Perl Programming A D Marshall 1999-2005

Note Signals that are sent to your script can bypass the END blocks.

Would someone explain this?

解决方案

This works for me: Re-install the handler in the END block that runs first (last in code).

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" };
}

When started and Ctrl-C-ed after a few seconds this prints

done.
END, runs next to last. Sleep then print
^CSIGINT in END block, got zap
Woke up.
END, runs last

So you need to add an END block, last in the code, END { $SIG{INT} = 'IGNORE' }.

It appears that the change to "END" ${^GLOBAL_PHASE} removes or otherwise disables the handler.

But once the handler is re-installed in the END phase it is effective throughout. It's cleanest of course to do that in the END block that is executed first.

I will update when (if) I understand more detail and find documentation on this behavior.

这篇关于Perl 信号处理程序在 END 块中重置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆