【问题标题】:What's the difference between ignoring a signal and telling it to do nothing in Perl?在 Perl 中忽略一个信号和告诉它什么都不做有什么区别?
【发布时间】:2009-07-29 03:22:08
【问题描述】:

如果我告诉 Perl 显式忽略一个信号,SIGINT 就没有效果:

$SIG{INT} = 'IGNORE';
my $count = 0;
say $count++ and sleep 1 while 1;

然后按 Control-C,很明显,没有任何效果。另一方面,如果我告诉它什么都不做:

$SIG{INT} = sub { };
my $count = 0;
say $count++ and sleep 1 while 1;

然后按Control-C就有效果了!它从 sleep() 调用中唤醒程序并立即增加计数。忽略一个信号和告诉它什么都不做有什么区别?

在我的程序中,我想让代码在 SIGINT 上运行, 不会破坏任何东西。我想要类似的东西:

$SIG{INT} = sub { say "Caught SIGINT!"; return IGNORED; };  # runs without disrupting sleep

【问题讨论】:

  • 您的信号处理程序如何在不中断当前运行的情况下运行?信号处理逻辑必须知道在信号发生之前应该发生什么。

标签: perl signals


【解决方案1】:

忽略一个信号和告诉它什么都不做有什么区别?

在传递信号时仍会调用您的“什么都不做”处理程序,在这种情况下会中断 sleep 调用。另一方面,忽略的信号会被系统简单地丢弃,对进程没有任何影响。

请参阅 here 以获取特定于 C 但更全面的参考。

【讨论】:

    【解决方案2】:

    许多系统调用可能会被信号传递中断。通常你可以检查$!(又名errno),看看它是否是EINTR,然后采取措施重试失败的系统调用。

    如果您的代码的某些部分(在这种情况下,您对 sleep() 的调用)不被中断对您很重要,那么您可以在您处于关键部分时使用 POSIX::sigprocmask 来阻止信号。应用程序接收到的任何信号都将排队,直到您取消阻止它们,此时它们将被传递。我很确定当特定类型的多个信号被阻塞时会有一些有趣的语义(我认为它们可能会合并成一个信号)。

    这是来自 IBM 的关于可重入函数的 nice primer,其中包含一个带有 sigprocmask 的小示例。

    【讨论】:

    • +1。我的理解是大多数 UNIX 变体绝对会合并相同类型的多个信号。因此,当您看到信号 XYZ 时,您可以确定的是 XYZ 被提出至少一次
    【解决方案3】:

    不知道为什么它没有按预期工作,但通常当我尝试完成类似的事情时,除了 INT 信号之外,我还会捕获 TERM 信号。

    【讨论】:

      猜你喜欢
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 2019-05-22
      • 2020-10-15
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 2010-10-30
      相关资源
      最近更新 更多