忽略一个信号并告诉它在Perl中什么也不做的区别是什么?

时间:2009-07-28 13:29:35

标签: perl signals

如果我告诉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

3 个答案:

答案 0 :(得分:13)

  

忽略信号并告诉它什么都不做之间的区别是什么?

当信号传递时,仍然会调用“不执行任何操作”处理程序,在这种情况下会中断sleep调用。另一方面,忽略的信号被系统简单地丢弃,对过程没有任何影响。

有关特定于C的更全面的参考,请参阅here

答案 1 :(得分:6)

信号传递可能会中断很多系统调用。通常,您可以检查$!(又名errno)以查看它是否为EINTR并采取措施重新尝试失败的系统调用。

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

以下是IBM关于重入函数的nice primer,其中包含一些sigprocmask的示例。

答案 2 :(得分:1)

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