散列 %SIG
包含信号的信号处理程序。例如
sub handler { # 1st argument is signal name
my($sig) = @_;
print "Caught a SIG$sig--shutting down\n";
close(LOG);
exit(0);
}
$SIG{'INT'} = \&handler;
$SIG{'QUIT'} = \&handler;
...
$SIG{'INT'} = 'DEFAULT'; # restore default action
$SIG{'QUIT'} = 'IGNORE'; # ignore SIGQUIT
使用值 'IGNORE'
通常会忽略信号,但 CHLD
信号除外。有关此特殊情况的更多信息,请参阅 perlipc。使用空字符串或 undef
作为值与 'DEFAULT'
的效果相同。
以下是一些其他示例
$SIG{"PIPE"} = "Plumber"; # assumes main::Plumber (not
# recommended)
$SIG{"PIPE"} = \&Plumber; # just fine; assume current
# Plumber
$SIG{"PIPE"} = *Plumber; # somewhat esoteric
$SIG{"PIPE"} = Plumber(); # oops, what did Plumber()
# return??
确保不要将裸字用作信号处理程序的名称,以免无意中调用它。
使用不对应于任何现有函数的字符串或不包含代码槽的 glob 等效于 'IGNORE'
,但在调用处理程序时会发出警告(对于下面描述的内部钩子不会发出警告)。
如果您的系统具有 sigaction()
函数,则使用它安装信号处理程序。这意味着您可以获得可靠的信号处理。
信号的默认传递策略在 Perl v5.8.0 中从立即(也称为“不安全”)更改为延迟,也称为“安全信号”。有关更多信息,请参阅 perlipc。
某些内部挂钩也可以使用 %SIG
哈希设置。当警告消息即将打印时,将调用由 $SIG{__WARN__}
指示的例程。警告消息作为第一个参数传递。存在 __WARN__
挂钩会导致对 STDERR
的普通警告打印被禁止。你可以使用它将警告保存在变量中,或将警告变为致命错误,如下所示
local $SIG{__WARN__} = sub { die $_[0] };
eval $proggie;
由于 'IGNORE'
挂钩不受 __WARN__
支持,因此其效果与使用 'DEFAULT'
相同。你可以使用空子例程禁用警告
local $SIG{__WARN__} = sub {};
当致命异常即将抛出时,将调用由 $SIG{__DIE__}
指示的例程。错误消息作为第一个参数传递。当 __DIE__
挂钩例程返回时,异常处理将继续,就像在没有挂钩的情况下一样,除非挂钩例程本身通过 goto &sub
、循环退出或 die()
退出。在调用期间,将显式禁用 __DIE__
处理程序,以便你可以从 __DIE__
处理程序中退出。__WARN__
类似。
即使在 eval()
内,也会调用 $SIG{__DIE__}
挂钩。它从未打算以这种方式发生,但实现故障使之成为可能。这曾经是不赞成的,因为它允许在 $@
中重写挂起的异常等奇怪的远程操作。纠正此问题的计划已被废弃,因为用户发现重写挂起的异常实际上是一个有用的特性,而不是一个错误。
$SIG{__DIE__}
不支持 'IGNORE'
;它具有与 'DEFAULT'
相同的效果。
__DIE__
/__WARN__
处理程序在一个方面非常特殊:它们可能会被调用来报告解析器发现的(可能的)错误。在这种情况下,解析器可能处于不一致的状态,因此尝试从这样的处理程序中评估 Perl 代码可能会导致段错误。这意味着应极其谨慎地使用由解析 Perl 产生的警告或错误,如下所示
require Carp if defined $^S;
Carp::confess("Something wrong") if defined &Carp::confess;
die "Something wrong, but could not load Carp to give "
. "backtrace...\n\t"
. "To see backtrace try starting Perl with -MCarp switch";
这里,第一行将加载 Carp
,除非是解析器调用了处理程序。如果 Carp
可用,第二行将打印回溯并退出。只有在 Carp
不可用的情况下,才会执行第三行。
在你的异常处理程序中甚至必须考虑 $^S
变量是错误的。当前实现的 $SIG{__DIE__}
会引发严重且难以追踪的错误。避免它,而使用 END{}
或 CORE::GLOBAL::die 覆盖。