6

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

3 回答 3

13

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

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

有关特定于 C 的但更全面的参考,请参见此处

于 2009-07-28T13:38:50.967 回答
6

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

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

这是 IBM 提供的关于可重入函数的不错的入门指南,其中包含一个带有sigprocmask.

于 2009-07-28T15:29:53.950 回答
1

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

于 2009-07-28T13:38:03.900 回答