[Moscow.pm] И все-таки, как правильно перехватить исключение?

Ivan Petrov i.petro.77.00 на gmail.com
Сб Мар 23 13:14:00 PDT 2013


задача:

- перехватить исключение

подзадачи:

 - передать исключение на более верхний уровень в измененном виде
 - точно определить место где произошло исключение которое мы
   перехватили


решение второй подзадачи приводит нас к двум вариантам.

вариант №1
~~~~~~~~~~

eval { 
  ... код с исключением    
};

if ($@) {
    тут выпарсиваем место исключения из $@;
}

этот вариант очевидно ущербный в силу парсинга: в современных perl'ах,
а так же в всяких расширениях получается что не всегда можно точно
распарсить.


вариант №2
~~~~~~~~~~

local $SIG{__DIE__} = sub {
    тут по значению, возвращенному функцией caller определяем место
    исключения
    ...
    die $_[0];
};
тут код выбрасывающий исключение

но второй вариант ущербен в связи с тем обстоятельством что невозможен
иерархический перехват.

то есть если код какого-либо модуля тоже хватает $SIG{__DIE__}, то мы
не можем определить место падения иначе как парся $@.

вот пример:

sub foo1 {
    local $SIG{__DIE__} = sub {
        print "die 1\n";
        die $_[0];
    };
    die "привет 1";
}


sub foo2 {
    local $SIG{__DIE__} = sub {
        print "die 2\n";
        die $_[0];
    };
    foo1;
}

foo2;

данная программа выводит строку 'die 1', а 'die 2', разумеется не
будет  выведен никогда. если предположить что foo1 у нас в стороннем
модуле, то задача не решена.


есть еще какие-то мысли как перехватить исключение с точным
определением места исключения?


а общая задача банальная:

1. имеется некое большое приложение.
2. в этом приложении на самом верхнем уровне мы перехватываем
исключения и отправляем email о том что оно произошло
3. хотим дополнительно в письме отправить stacktrace, соответственно
код такой:

$SIG{__DIE__} = sub {
    собираем stacktrce и определяем место где упало
    die $_[0];
};

eval { main };
if ($@) {
    отправляем email со stacktrace сохраненным в SIG{__DIE__}.
}

такой подход работает, все красиво, но есть куча внешних модулей (как
оказывается) которые так же ловят SIG{__DIE__}

у кого какие мысли?


Подробная информация о списке рассылки Moscow-pm