如果我告诉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
答案 0 :(得分:13)
忽略信号并告诉它什么都不做之间的区别是什么?
当信号传递时,仍然会调用“不执行任何操作”处理程序,在这种情况下会中断sleep
调用。另一方面,忽略的信号被系统简单地丢弃,对过程没有任何影响。
有关特定于C的更全面的参考,请参阅here。
答案 1 :(得分:6)
信号传递可能会中断很多系统调用。通常,您可以检查$!
(又名errno
)以查看它是否为EINTR
并采取措施重新尝试失败的系统调用。
如果您的代码的某些部分(在这种情况下,您对sleep()
的调用)没有中断对您很重要,那么您可以使用POSIX::sigprocmask
阻止信号关键部分。应用程序收到的任何信号都将排队,直到您取消阻止它们为止,此时它们将被传递。我很确定当特定类型的多个信号被阻塞时会有一些有趣的语义(我认为它们可能合并成一个信号)。
以下是IBM关于重入函数的nice primer,其中包含一些sigprocmask
的示例。
答案 2 :(得分:1)
不确定为什么它没有按预期工作,但通常当我尝试完成类似的事情时,除了INT信号之外我还会捕获TERM信号。