%SIG

散列 %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 覆盖。

有关其他信息,请参见 perlfunc 中的 "die""warn""eval"warnings