雜湊 %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」 和 警告 以取得更多資訊。