Johannes Schlüter wrote on 28/10/2015 22:56:
On Wed, 2015-10-28 at 16:45 +0000, Rowan Collins wrote:
On the downside, it's worth noting that while PHP destructors are
technically deterministic, the language can actually prevent them
running on scope exit, because Exceptions hold references to everything
used as a parameter in their stack traces.

In the below very simple example, both err() and foo() have completed,
but the destructor fires only once the Exception is caught and
discarded. So if you passed your ScopeGuard object around at all, you
might find things executing in a surprising order.
That's an interesting case, I in fact didn't think about, but I believe
a scope guard / RAII object should not be passed to another scope.

It's definitely an edge-case, and a class dedicated to RAII as an abstract concept would probably never hit it, but if you consider RAII as just one aspect/"trait" of another object, it could be problematic. Note that the function throwing the Exception need not be interacting directly with the object:

function do_something_with_a_file($filename) {
$fh = new RAIIFileHandle($filename);
// ...
$this->refactored_code_which_got_too_long($fh);
// ...
}

function refactored_code_which_got_too_long($fh) {
// ...
$this->get_db_lookup_table();
// ...
}

function get_db_lookup_table() {
if ( ! $this->db ) {
throw new DB_Connection_Exception;
}
}

The assumption is that an instance of RAIIFileHandle will close the underlying file handle as soon as control leaves do_something_with_a_file; this assumption holds across the refactoring to multiple functions. However, if the DB is disconnected, the file handle stays open until the stack has rewound to some generic error handler, because the stack trace contains an entry for refactored_code_which_got_too_long complete with a counted reference to its parameter.

Thinking about it, this example probably holds for built-in Resource types as well.

Regards,
--
Rowan Collins
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to