%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;

由於 __WARN__ 不支援 'IGNORE' 掛鉤,因此其效果與使用 '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 可用時執行 die。第三行只會在 Carp 不可用時執行。

在你的例外處理常式中甚至必須考慮 $^S 變數根本就是錯誤的。$SIG{__DIE__} 根據目前的實作會引發嚴重且難以追蹤的錯誤。避免使用它,而改用 END{} 或 CORE::GLOBAL::die 覆寫。

請參閱 perlfunc 中的「die」perlfunc 中的「warn」perlfunc 中的「eval」警告 以取得更多資訊。