Good afternoon, Habr!
The other day I encountered the behavior of finally in php version 5.5 which I did not expect and, I think, many do not know about it.
The essence of the error is as follows. We have a try-finally block. In try throws Exception. Further, in finally, the code is executed that throws its Exception in the process and catches it. In this case, the first Exception, which should fly out of try, is forgotten.
')
Under the cut there is a refined example of an error and a couple of conclusions about the possibility of using finally in 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";
In 5.6 the result is expected: 1 2 3 4 + E1 5.
In 5.5, to my surprise, I received 1 2 3 5
(the results of the implementation can be viewed at
3v4l.org )
I
made a mistake the day before in bugs.php.net and already managed to get the following answer:
after finally supporting was merged into 5.5. we did a refactor to it for performance ……
This is an abi compitiable
Those. in my free translation, it turns out that the problem is related to the fact that after finally was added in 5.5, it was refactored to improve performance and in the new implementation, an additional EG field is needed to fix the error, but it breaks the API for 18 times already patched can not be done.
The following conclusions can be drawn from the circumstances:
- in calm, you can use very simple actions in which there are guaranteed no mechanisms for catching Exception
- in finally, you can use proven code about the work of which everything is known and in which there is no mechanism for catching Exception at all
- if your autoloader uses Excepts itself, then using finally with code that creates new objects or uses static methods, variables or constants (i.e., code where the autoloader is implicitly possible) can lead to the loss of Exception
- stop using finally before upgrading to version 5.6
UPD if they forget about this error now, which is more than likely, then it will most likely come up when the frameworks stop supporting version 5.4, but still support 5.5 and start using the long-awaited finally.
I caught it myself when I had a piece of code that worked differently depending on whether I used a logger in a finally or not. To my surprise, there was no limit, and I went through the whole Monolog until I found that it was in a self-written adapter writing logs to the database and catching errors when writing. And even in this case, I did not immediately begin to believe that the matter was in php and the search area of the bug was gradually narrowed until I reduced it to the code written in this note above :)