Bug #72011 [Com]: DateTime serializes as empty object

From: Date: Tue, 14 Jun 2016 21:20:06 +0000
Subject: Bug #72011 [Com]: DateTime serializes as empty object
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-201622@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=72011&edit=1

 ID:                 72011
 Comment by:         bill at zeroedin dot com
 Reported by:        benjamin dot roth at jaumo dot com
 Summary:            DateTime serializes as empty object
 Status:             Open
 Type:               Bug
 Package:            Date/time related
 Operating System:   Linux
 PHP Version:        7.0.5
 Block user comment: N
 Private report:     N

 New Comment:

Basically that code just makes a lot of work for the garbage collector to do, then waits until the
execution time is almost up, and triggers the garbage collector so that the execution time expires
while the garbage collector is running. Or at least I *think* that's what it's doing. Who
knows.


Previous Comments:
------------------------------------------------------------------------
[2016-06-14 21:16:05] bill at zeroedin dot com

@nikic thanks! I'll be running with execution time and memory limits relaxed for now, but once
the patch hits a release I'll bump things back down and retest.

I still can't reliably reproduce the issue. Is it possible that the garbage collector is
allocating just enough memory at some stage to trigger the memory exhaustion error? I managed to get
a segfault out of it on both linux and windows, fpm and cli, 5.6.22 and 7.0.4, but not the broken
DateTime behavior.

<?php
// Segfault this shizz
$start = microtime(true);
set_time_limit(3);
ini_set('display_errors', 1);
error_reporting(E_ALL);

function shutdownFunc()
{
    if (!is_null($e = error_get_last()))
    {
        echo serialize(new DateTime);
    }
}

register_shutdown_function('shutdownFunc');
$a = new stdClass();
$a->next = $a;
$last = $a;
$mem_start = memory_get_usage();
echo "Building cycle...\n";
while((microtime(true) - $start < 2.9) && (memory_get_usage() - $mem_start) <
1024*1024*128) {
    $b = new stdClass();
    $last->next = $b;
    $b->next = $a;
    $last = $b;
}
$i=0;
echo "Waiting...\n";
while ((microtime(true)-$start < 2.9)) {
    $i++;
}
unset ($last);
unset ($a);
echo "Explode!\n";
gc_collect_cycles();

------------------------------------------------------------------------
[2016-06-14 20:46:41] nikic@php.net

@bill: Thanks! I've now applied https://github.com/php/php-src/commit/248fdfcf7356f2c20ab1e6afd1e9f295d08331c7
to 5.6 and upwards, which will hopefully fix the problem.

We should probably still either catch bailouts during GC and reset state, or at least reset the GC
state for new requests.

------------------------------------------------------------------------
[2016-06-14 20:11:31] bill at zeroedin dot com

Actually yes, this bug has consistently appeared after a maximum execution time or allowed memory
exhaustion bailout. After increasing the timeout in our dev environment, the bug has not reappeared,
but I haven't tested the allowed memory ceiling yet.

------------------------------------------------------------------------
[2016-06-14 19:39:02] nikic@php.net

Going out on a limb here ... this might be happening because serialize() is called while
gc_active=1. The DateTime get_properties handler contains a check that will return an empty
properties HT in that case. What's not clear here is how serialize() could be called while
gc_active=1. My guess would be that somehow a fatal error is triggered during GC, causing a bailout
without resetting the flag. This would be consistent with following requests experiencing the same
issue, as the flag would stay enabled.

Do any of see fatal errors (e.g. due to timeout, memory limit, OOM) in your logs around the time
this issue starts to occur?

Even if this should be totally unrelated, we should still drop those gc_active checks ... they
aren't necessary as long as everything defines a proper get_gc handler.

------------------------------------------------------------------------
[2016-06-14 19:16:41] benjamin dot roth at jaumo dot com

In my case (PHP7) it is with opcache:

zend_extension=opcache.so

opcache.optimization_level=0xffffffff

----

PHP 7.0.5-2+deb.sury.org~trusty+1 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

------------------------------------------------------------------------


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=72011


--
Edit this bug report at https://bugs.php.net/bug.php?id=72011&edit=1


Thread (19 messages)

« previous php.bugs (#201622) next »