Bug #74569 [Com]: Return in a finally clause silently ignores an exception thrown in a try clause
| From: | trianman at gmail dot com | Date: | Fri, 12 May 2017 18:24:18 +0000 |
| Subject: | Bug #74569 [Com]: Return in a finally clause silently ignores an exception thrown in a try clause | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-209087@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=74569&edit=1
ID: 74569
Comment by: trianman at gmail dot com
Reported by: trianman at gmail dot com
Summary: Return in a finally clause silently ignores an
exception thrown in a try clause
Status: Open
Type: Bug
Package: Scripting Engine problem
Operating System: Any
PHP Version: 7.1.4
Block user comment: N
Private report: N
New Comment:
2 danack@php.net
Sorry, I don't want to be mean. My English skills are not very good and it is sometimes hard to
express my thoughts in a clear way.
I've just realized that the finally statement is some-kind of antipattern for me. Because
finally is a shortcut for catching and re-throwing an \Exception class eg.
<?php
try {
throw new CustomException();
} catch (CustomException $ex) {
handleException();
} catch (\Exception $ex) {
doThingsInFinally();
throw $ex;
}
doThingsInFinally();
?>
Or with finally:
<?php
try {
throw new CustomException();
} catch (CustomException $ex) {
handleException();
} finally {
doThingsInFinally();
}
?>
Of cause if we have a return statement instead of a doTihingsInFinally() method, we will lose an
exception. But we doing it in a clear way. On the other hand finally statement hides out from
developer's eyes what actually is going.
So for my mind a little copy-paste is a lesser evil than an unclear behavior. For all other guys the
E_NOTICE will be enough. (:
Previous Comments:
------------------------------------------------------------------------
[2017-05-11 14:28:34] olavisau at gmail dot com
BC is broken with any solution. The fact that javascript behaves in the same way worries me.
It's probably very hard to implement. I agree with the E_NOTICE.
------------------------------------------------------------------------
[2017-05-11 14:21:03] trianman at gmail dot com
> btw The behaviour in PHP is the same as that which happens in Java
> This behaviour is also that used in Javascript.
Sorry to hear that, but AFAIK nor Java nor JavaScript (ECMAScript) has no conventional
(standartized) way to produce non critical warnings at the run time.
So PHP is better in this way and why can't we employ it?
> "Don't put returns in finally"
I believe that the good tool must help its users not to "shoot themselves" as much as
possible. So the user becomes free from a lot of "Don't do something somewhere". If
you don't agree you are free to use an assembler to do anything you want and remember a lot of
such restrictions.
I can imagine another more expectable an clear way to handle this case. But it will break a BC so
can be implemented only in a new major release of PHP.
Triggering E_NOTICE is the most convenient way for now.
------------------------------------------------------------------------
[2017-05-11 13:42:04] danack@php.net
This behaviour is also that used in Javascript.
function foo() {
try {
throw 42;
}
finally {
return "edge cases are hard";
}
};
alert(foo());
------------------------------------------------------------------------
[2017-05-11 13:30:49] danack@php.net
> but it MUST NOT be silently dropped out.
That's a conclusion without rigorous justification.
btw The behaviour in PHP is the same as that which happens in Java: https://web.archive.org/web/20070922061412/http://weblogs.java.net/blog/staufferjames/archive/2007/06/_dont_return_in.html
It'd be a lot easier to say "Don't put returns in finally blocks, yo".
> The interpreter should trigger an E_NOTICE or something similar here.
This would almost certainly be better done with code analysis tools, rather than giving warnings on
valid (though highly surprising) code.
------------------------------------------------------------------------
[2017-05-11 07:41:34] olavisau at gmail dot com
The correct way of writing this would be to catch the exception and throw it again, however this
also fails. If it is not thrown again, then the behavior is correct.
<?php
class MyException extends Exception
{
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
print "2. Exception constructed\n";
}
}
function throw_exception() {
try {
throw new MyException("5. Exception message\n");
} catch(Exception $exception) {
print "3. Exception caught and thrown again\n";
throw $exception;
} finally {
return "4. Return statement\n";
}
}
try {
print "1. Start\n";
print throw_exception();
} catch (Exception $e) {
print $e->getMessage();
}
The flow should be: exception is thrown, caught by the inner block, thrown again, caught by the
outer block and then the finally block should execute, returning the flow to
print throw_exception();
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=74569
--
Edit this bug report at https://bugs.php.net/bug.php?id=74569&edit=1