У меня есть фрагмент кода на 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();
}
[ EDIT : я допустил ошибку, приведенный выше код на самом деле не работает так, как я хочу, он фактически обходит обработку исключений в подпрограмме middle
. Так что я думаю, что вопрос должен быть: возможно ли такое поведение, которое я хочу?]
Это прекрасно работает , единственная проблема в том, что, если я правильно понимаю документы, он опирается на явное устаревшее поведение, а именно на тот факт, что обработчики __DIE__
запускаются даже для "die
"внутри" eval { }
, что они действительно не должны. И perlvar
, и perlsub
утверждают, что это поведение может быть удалено в будущих версиях Perl.
Есть ли другой способ, которым я могу достичь этого, не полагаясь на устаревшее поведение, или это безопасно, на которое можно положиться, даже если в документах сказано иначе?