次のような Perl コードがあります (大幅に簡略化されています): ネストされたサブルーチン呼び出し (実際にはメソッド) にはいくつかのレベルがあり、内部のいくつかは独自の例外処理を行います:
sub outer { middle() }
sub middle {
eval { inner() };
if ( my $x = $@ ) { # caught exception
if (ref $x eq 'ARRAY') {
print "we can handle this ...";
}
else {
die $x; # rethrow
}
}
}
sub inner { die "OH NOES!" }
次に、そのコードを次のように変更します。
最も外側のレベルまで「バブルアップ」するすべての例外の完全なスタック トレースを出力します (
sub outer
)。具体的には、スタック トレースが " " の最初のレベルで停止しないeval { }
ようにする必要があります。内部レベルの実装を変更する必要はありません。
現在、これを行う方法は、サブ__DIE__
内にローカライズされたハンドラーをインストールすることです。outer
use Devel::StackTrace;
sub outer {
local $SIG{__DIE__} = sub {
my $error = shift;
my $trace = Devel::StackTrace->new;
print "Error: $error\n",
"Stack Trace:\n",
$trace->as_string;
};
middle();
}
[編集: 間違いを犯しました。上記のコードは実際には思い通りに動作しませんmiddle
。実際には、サブルーチンの例外処理をバイパスします。だから私は質問が本当にあるべきだと思います:私が望む動作は可能ですか?]
これは完全に機能します、唯一の問題は、私がドキュメントを正しく理解していれば、明示的に廃止された動作に依存している__DIE__
ことdie
ですeval { }
。と の両方perlvar
でperlsub
、この動作は Perl の将来のバージョンで削除される可能性があると述べています。
非推奨の動作に頼らずにこれを達成できる別の方法はありますか、それともドキュメントが別のことを言っていても頼りにできますか?