<div dir="ltr"><div>Вариант 1 ещё и неверный.<br><br><div><div><div><div>eval {<br></div>    # code<br></div>    1; # return true<br></div>} or do {<br></div>    my $error = $@ || "Zombie error";<br></div>    # parse $error<br>
<div>}<br><br></div><div>Существуют ещё всякие TryCatch, Try::Tiny и т.п.<br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">23 марта 2013 г., 21:14 пользователь Ivan Petrov <span dir="ltr"><<a href="mailto:i.petro.77.00@gmail.com" target="_blank">i.petro.77.00@gmail.com</a>></span> написал:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">задача:<br>
<br>
- перехватить исключение<br>
<br>
подзадачи:<br>
<br>
 - передать исключение на более верхний уровень в измененном виде<br>
 - точно определить место где произошло исключение которое мы<br>
   перехватили<br>
<br>
<br>
решение второй подзадачи приводит нас к двум вариантам.<br>
<br>
вариант №1<br>
~~~~~~~~~~<br>
<br>
eval {<br>
  ... код с исключением<br>
};<br>
<br>
if ($@) {<br>
    тут выпарсиваем место исключения из $@;<br>
}<br>
<br>
этот вариант очевидно ущербный в силу парсинга: в современных perl'ах,<br>
а так же в всяких расширениях получается что не всегда можно точно<br>
распарсить.<br>
<br>
<br>
вариант №2<br>
~~~~~~~~~~<br>
<br>
local $SIG{__DIE__} = sub {<br>
    тут по значению, возвращенному функцией caller определяем место<br>
    исключения<br>
    ...<br>
    die $_[0];<br>
};<br>
тут код выбрасывающий исключение<br>
<br>
но второй вариант ущербен в связи с тем обстоятельством что невозможен<br>
иерархический перехват.<br>
<br>
то есть если код какого-либо модуля тоже хватает $SIG{__DIE__}, то мы<br>
не можем определить место падения иначе как парся $@.<br>
<br>
вот пример:<br>
<br>
sub foo1 {<br>
    local $SIG{__DIE__} = sub {<br>
        print "die 1\n";<br>
        die $_[0];<br>
    };<br>
    die "привет 1";<br>
}<br>
<br>
<br>
sub foo2 {<br>
    local $SIG{__DIE__} = sub {<br>
        print "die 2\n";<br>
        die $_[0];<br>
    };<br>
    foo1;<br>
}<br>
<br>
foo2;<br>
<br>
данная программа выводит строку 'die 1', а 'die 2', разумеется не<br>
будет  выведен никогда. если предположить что foo1 у нас в стороннем<br>
модуле, то задача не решена.<br>
<br>
<br>
есть еще какие-то мысли как перехватить исключение с точным<br>
определением места исключения?<br>
<br>
<br>
а общая задача банальная:<br>
<br>
1. имеется некое большое приложение.<br>
2. в этом приложении на самом верхнем уровне мы перехватываем<br>
исключения и отправляем email о том что оно произошло<br>
3. хотим дополнительно в письме отправить stacktrace, соответственно<br>
код такой:<br>
<br>
$SIG{__DIE__} = sub {<br>
    собираем stacktrce и определяем место где упало<br>
    die $_[0];<br>
};<br>
<br>
eval { main };<br>
if ($@) {<br>
    отправляем email со stacktrace сохраненным в SIG{__DIE__}.<br>
}<br>
<br>
такой подход работает, все красиво, но есть куча внешних модулей (как<br>
оказывается) которые так же ловят SIG{__DIE__}<br>
<br>
у кого какие мысли?<br>
<span class="HOEnZb"><font color="#888888">--<br>
Moscow.pm mailing list<br>
<a href="mailto:moscow-pm@pm.org">moscow-pm@pm.org</a> | <a href="http://moscow.pm.org" target="_blank">http://moscow.pm.org</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Andrei Protasovitski<br>< andrei[dot]protasovitski[at]gmail[dot]com ><br>Diemen, Netherlands
</div>