【问题标题】:Perl signal handlers are reset in END blocksPerl 信号处理程序在 END 块中重置
【发布时间】:2017-04-02 23:23:16
【问题描述】:

这从 Perl 5.10.1 开始按预期工作:SIGINT 被捕获。

#!/usr/bin/perl

use strict;
use warnings;

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

sleep(20);

但是这里 SIGINT 被困住了。

#!/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 块。

有人能解释一下吗?

【问题讨论】:

  • 在 5.24 上工作正常(似乎)。没有时间测试,但是如果您将 sig 处理程序放在 5.10 上的 BEGIN 块中会发生什么......这会改变什么吗?我希望并且不认为...
  • 我在家里用 5.22 再次测试了它,我也有同样的行为。然后启动 Ctrl-C -> Caught...,结束块:。至于 BEGIN 块,在 5.22 上,将处理程序设置在那里会捕获信号,但也有一个 END 块,信号仍然未被捕获。
  • 你个人好像觉得委屈。没有人把你挑出来。 Perl 是一种编程语言,如果您与我们其他信任和尊重该语言但偶尔发现需要修复的错误的人一起,您会更快地得到更好的答案。在这种情况下,END 块禁用信号我并不感到惊讶,否则它可能导致无限循环。您是否要求提供有关 Perl 版本之间更改的文档?
  • 我应该解释一下,我已将您的问题编辑为不那么尖锐,我的批评与您的原始帖子有关。
  • @gxtaillon:Perl 的创建者 Larry Wall 写道,“Perl 并不迷恋强制隐私。它宁愿你呆在它的客厅之外,因为你不是没有被邀请,不是因为它有猎枪”

标签: perl signals perl5.10


【解决方案1】:

这对我有用:在第一个运行的 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 时会打印出来

完毕。 END,倒数第二个。睡眠然后打印 ^CSIGINT 在 END 块中,得到 zap 醒了。 END,最后运行

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

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

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

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

【讨论】:

    【解决方案2】:

    perldoc perlmod 说:

    尽可能晚执行一个“END”代码块,即之后 @987654322 @ 已经完成了程序的运行,就在解释器正在运行之前 退出,即使它是由于die() 函数而退出。 (但如果不是 它正在通过“exec”变成另一个程序,或者被吹出 通过信号来浇水——你必须自己捕捉它(如果可以的话)。

    我希望在退出解释器之前删除信号处理程序。因此,我不太能看出什么是令人惊讶或意料之外的。

    【讨论】:

      猜你喜欢
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-01
      • 1970-01-01
      相关资源
      最近更新 更多