Re: Re: Serializing exceptions

From: Date: Sun, 02 Aug 2015 17:50:50 +0000
Subject: Re: Re: Serializing exceptions
References: 1 2 3 4 5 6 7 8 9  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
On 01/08/2015 01:06, Rowan Collins wrote:
On 1 August 2015 00:36:58 BST, Stanislav Malyshev <[email protected]> wrote:
DEBUG_BACKTRACE_IGNORE_ARGS in a debug_backtrace() call. IIRC the object of called methods is already excluded (equivalent to masking out DEBUG_PROVIDE_OBJECT) so what's left is all strings.
I'm not sure how you arrived at the conclusion that all arguments in backtrace are strings. Arguments can be of any type. When printed, they are converted to strings, but they are not strings when stored.
I'll have to recheck when I have more time, and something better than a phone to type on, but from memory, the backtrace which can be retrieved from an exception includes the same information as debug_backtrace(false), that is: - function: string - line: integer - file: string - class: string - type: string - args: array Of these 6 items, it is only 'args' that can contain an object of any kind, so without this item, the data would be serializable. This would be equivalent to debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS). If any of these items (other than args) are stored in memory in a different form (which doesn't seem likely to me), that form is completely inaccessible to the user, so converting to string during serialization would effectively be lossless. (Or, pre-converting would have zero BC break.) Similarly, if additional details are stored, those details are inaccessible, so removing them has no impact on any existing (userland) code.
I just double-checked this. You can see that there is not even an internal reference to objects which were $this in the stack trace, because the object can be garbage collected separately from the exception. http://3v4l.org/hOYb9 So, as I said, no object will be implicitly attached to the exception anywhere other than the 'args' key of the backtrace. Obviously, people can attach object references wherever they like, but without this implicit gathering of objects from the entire environment, "serialize(new Exception)" would be a safe operation. Slightly abbreviated version: class Example {
    private $label;
    public function __construct($label) {
        $this->label = $label;
    }
    public function __sleep() {
        echo "Attempt to serialize object with label $this->label\n";
        return array('label');
    }
    public function __destruct() {
        echo "Refcount reached zero for object with label $this->label\n";
    }
    public function throwSomething($unused_parameter) {
        throw new Exception;
    }
} $target = new Example('Target of method call'); $parameter = new Example('Parameter passed but never actually used'); try {
    $target->throwSomething($parameter);
} catch ( Exception $e ) {
    // Serialize exception, will attempt to serialize $parameter but not $target
    var_dump(serialize($e));
    // Destroy $target, as there are no other references to it
    unset($target);
    // Attempt to do the same for $parameter, but Exception holds a reference
    unset($parameter);
} echo "-- PHP process cleanup begins here --\n"; // $parameter will have its destructor fired once $e goes out of scope and relinquishes its reference Regards, -- Rowan Collins [IMSoP]

Thread (33 messages)

« previous php.internals (#87524) next »