Hi All,

A while ago, I discovered the awkward fact that PHP exceptions can only sometimes be serialized, because they contain a stack trace which might involve non-serializable objects.

In my case, one of the function calls in the trace happened to have been passed a SimpleXMLElement as an argument; similarly, anything passed a closure will render the trace unserializable. A quick example is here: http://codepad.viper-7.com/A6U91A

When I mentioned this in SO chat, the general response was "yeah, don't do that". Which leads me to my first suggestion: (1) the base Exception class should *always* prevent serialization, in the same way that it always prevents cloning. This would prevent people like me writing code to do it, and only finding out later that it is a Bad Idea.

(As background, my use case was some code that used serialized objects to pass call-backs and their responses between processes in a kind of "fake threading"; I wanted exceptions to bubble up to the parent "thread" just as though the callback had been executed locally.)

On the other hand, most of the Exception, including its trace *can* actually be serialized - an actual call to a closure is simply given the function name '{closure}', and the object on which a method was called is stored only as its class name, like debug_backtrace without DEBUG_BACKTRACE_PROVIDE_OBJECT. The only part that is at risk of causing serialization errors is the 'args' element in each stack trace entry.

This leads to two further possibilities:

(2) Don't capture arguments in the trace of an exception, similar to debug_backtrace with DEBUG_BACKTRACE_IGNORE_ARGS set. This would technically be a BC break, but I'm not sure how much real code would care. It's impossible to reconstruct details of the calls fully without the PROVIDE_OBJECT behaviour anyway.

This would also have the advantage of making destructors fire more predictably - at the moment, an exception can bubble past a block of code with a deliberately scoped object (e.g. an RAII-style lock token), and if that object happens to be an argument within the Exception's trace, it survives until the Exception itself is destructed, because it has a reference inside the Exception's trace. Again, arguably you shouldn't be relying on this or keeping Exception objects around for long anyway, but it's kind of unexpected behaviour.

Alternatively (3), serializing an Exception could discard the 'args' keys in the trace, but retain the rest of the information; or (4) a method could be made to explicitly discard these and mark the object safe for serialization. This lets code that relies on that informaion continue unchanged, while allowing the information needed for most use cases to be serialized as safely as any other object.

It seems to me that any one of these options would be better than the current unpredictable behaviour, but I'm more than willing for someone to point out the flaw in my reasoning.

Regards,
--
Rowan Collins
[IMSoP]

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

Reply via email to