Bug #75056 [Com]: Unintuitive gotcha - Exception maintains handles to stack objects
| From: | rowan dot collins at gmail dot com | Date: | Fri, 11 Aug 2017 20:42:30 +0000 |
| Subject: | Bug #75056 [Com]: Unintuitive gotcha - Exception maintains handles to stack objects | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-210617@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=75056&edit=1
ID: 75056
Comment by: rowan dot collins at gmail dot com
Reported by: nachms+php at gmail dot com
Summary: Unintuitive gotcha - Exception maintains handles to
stack objects
Status: Open
Type: Bug
Package: *General Issues
PHP Version: 5.6.31
Block user comment: N
Private report: N
New Comment:
This was actually one of the first topics I raised on the PHP Internals mailing list (which is
generally a better place for open-ended discussions like this - http://php.net/mailing-lists.php). That was nearly 4
years ago, and didn't get much response; it then came up again a couple of years later, in the
context of serialization errors (which are caused by the same data). See these threads in the
archives:
- http://marc.info/?t=138118341600002&r=1&w=2
- http://marc.info/?t=142708828500001&r=1&w=2
- http://marc.info/?t=143798102800002&r=1&w=2
The peculiar thing is that most of the information stored for the backtrace is already reduced to
strings (class names and the like), but the *arguments* passed to functions in the trace are
preserved as full object references. My inclination remains that removing these object references
would solve both the destructor and serialization problems, and I'm going to raise it on the
list again. I invite you to join the discussion there.
Previous Comments:
------------------------------------------------------------------------
[2017-08-09 15:05:07] nachms+php at gmail dot com
Description:
------------
Consider the attached code, it outputs:
The throw did not destruct
destructing
--------------
This is somewhat surprising at first, but is due to exceptions containing a backtrace of all
function parameters keeping objects alive somewhat unintuitively.
This really means that to have sane destruction behavior with exception handling, one must always
unset the Exception at the end of a catch. Which is usually fine...
However, if one needs to rethrow from an exception handler, this means objects that need to be
destructed as early as possible are now long-lived through many nested levels. There is no built-in
way in PHP to remove these handles from the exception's backtrace.
With the way PHP currently works, we've found that an exception to handle some occasional error
could in turn generate a whole chain reaction of problems simply because objects are now living far
outside their scope, holding onto resources they ideally should not.
We're not sure of the best solution here, but it would seem that in order to handle these kinds
of cases, PHP needs to offer a way to catch exceptions without keeping handles to stack objects.
Perhaps some other way to catch, or some way to tell Exceptions to drop object handles from their
backtrace before further handling them.
Test script:
---------------
<?php
$destructed = false;
class c
{
function __destruct()
{
global $destructed;
$destructed = true;
echo 'destructing', "\n";
}
}
function thrower($c) { throw(new Exception('oops')); }
function test()
{
$c = new c();
thrower($c);
}
try { test(); }
catch(Exception $e)
{
echo 'The throw ', ($destructed ? 'destructed' : 'did not
destruct'), "\n";
}
Expected result:
----------------
One would intuitively expect:
destructing
The throw destructed
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=75056&edit=1