У меня есть часть кода Perl, несколько похожая на следующую (сильно упрощенную): Есть несколько уровней вложенных вызовов подпрограмм (фактически, методы), а некоторые из внутренних выполняют свою обработку исключений:
sub outer { middle() }
sub middle {
eval { inner() };
if ( my $x = [email protected] ) { # 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
sub. Поэтому я думаю, что вопрос действительно должен быть: возможно ли поведение, которое я хочу, возможно?]
Это прекрасно работает, единственная проблема заключается в том, что, если я правильно понимаю документы, он полагается на поведение, которое явно не рекомендуется, а именно тот факт, что обработчики __DIE__
запускаются даже для "die
" внутри "eval { }
" s, чего они действительно не должны. Оба perlvar
и perlsub
указывают, что это поведение может быть удалено в будущих версиях Perl.
Есть ли другой способ, которым я могу достичь этого, не полагаясь на устаревшее поведение, или он сохраняет, чтобы полагаться, даже если документы говорят иначе?