Опасный finally или ждем 5.6
Добрый день, Хабр! На днях я столкнулся с поведением finally в php версии 5.5 которого не ожидал и, думаю, многие о нем не знают.
Суть ошибки в следующем. У нас есть блок try-finally. В try бросается Exception. Далее в finally выполняется код бросающий в процессе свой Exception и ловящий его. При этом первый Exception, который должен вылететь из try, забывается.
Под катом рафинированный пример ошибки и пара выводов о возможности использования finally в 5.5.
try { try { echo »1\n»; throw new Exception («E1»); } finally { try { echo »2\n»; throw new Exception («E2»); } catch (\Exception $e) { echo »3\n»; } } echo »4-\n»; } catch (\Exception $e) { echo »4+».$e→getMessage ().»\n»; } echo »5\n»; В 5.6 результат ожидаемый: 1 2 3 4+E1 5.В 5.5 же к моему удивлению я получил 1 2 3 5(результаты выполнения можно посмотреть на 3v4l.org)Ошибку я накануне завел в bugs.php.net и уже успел получить следующий ответ:
the problem is because, after finally supporting was merged into 5.5. we did a refactor to it for performance……and in the new implementation, we need a extra field in EG to fix this issue, which will break ABI compitiable, thus is not allowed to merge into 5.5
Т.е. в моем вольном переводе получается что проблема связана с тем что после того как finally был добавлен в 5.5 его отрефакторили для улучшения производительности и в новой реализации необходимо дополнительное поле EG что бы исправить ошибку, но это ломает API что для уже запатченной 18-ть раз 5.5 сделать нельзя.Следующие выводы можно сделать из сложившихся обстоятельств:
в finally спокойной можно использовать совсем простые действия в которых гарантированно нет механизмов с ловлей Exception’ов в finally можно использовать проверенный код о работе которого всё известно и в котором нет механизма ловли Exception’ов вообще в случае если ваш autoloader сам использует внутри Exception’ы, то использование finally с кодом создающим новые объекты или использующий статические методы, переменные или константы (т.е. код где неявно возможно задействование автолоадера) может повлечь за собой потерю Exception’а отказаться от использования finally до перехода на версию 5.6