Bug #63734 [Asn->Csd]: Garbage collector can free zvals that are still referenced
| From: | dmitry@php.net | Date: | Wed, 08 Apr 2015 19:20:53 +0000 |
| Subject: | Bug #63734 [Asn->Csd]: Garbage collector can free zvals that are still referenced | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-191904@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=63734&edit=1
ID: 63734
Updated by: dmitry@php.net
Reported by: lbarnaud@php.net
Summary: Garbage collector can free zvals that are still
referenced
-Status: Assigned
+Status: Closed
Type: Bug
Package: Reproducible crash
PHP Version: 5.4Git-2012-12-09 (Git)
Assigned To: dmitry
Block user comment: N
Private report: Y
New Comment:
Fixed in PHP-7.
Previous Comments:
------------------------------------------------------------------------
[2013-06-24 08:58:07] dmitry@php.net
hi Arnaud,
I afraid, I didn't understand your idea.
could you provide a patch?
------------------------------------------------------------------------
[2013-06-22 09:58:41] lbarnaud@php.net
Proposed mitigation (may not be right) :
After the GC has called destructors [1] and destroyed zvals [2], all zvals to be freed are expected
to have a refcount of 1 at [3] (to be verified; since all zvals referencing the zval have been
destroyed too, the only left reference should be the one added by the GC itself). If a zval has a
refcount > 1, it means that a reference to it has been created during step [1]. Converting the
zval to IS_NULL in [3] if refcount > 1, instead of freeing it, avoids use-after-frees.
[1] https://github.com/php/php-src/blob/a666285bc2488b7f7362368c388e41428610ad1d/Zend/zend_gc.c#L805
[2] https://github.com/php/php-src/blob/a666285bc2488b7f7362368c388e41428610ad1d/Zend/zend_gc.c#L824
[3] https://github.com/php/php-src/blob/a666285bc2488b7f7362368c388e41428610ad1d/Zend/zend_gc.c#L851
Improved reproducing script (causes segfault, and simplified):
<?php
global $ary;
class C {
public $ref;
public function __construct() {
$this->ref = $this;
}
public function __destruct() {
global $ary;
$ary[] = $this;
}
}
new C;
gc_collect_cycles();
var_dump($ary);
?>
------------------------------------------------------------------------
[2012-12-12 06:48:08] dmitry@php.net
Actually, I think it may be possible to detect mutation caused by destructors by complication of
collector, but not the zval and inc/dec refcount behavior.
After all the destructors called, me can put all the array and objects detected as garbage on the
first step back into "possible roots of cycles" buffer and run the same algorithm once
again. It's going to make GC about 2 times slower, and I'm not sure that this solution
will work at all.
Anyway, I won't have time in nearest future to test the idea. May be we can borrow something
from Java's GC & finalizers interactions, but papers, I read, refer to 3 times GC algorithm
complication because of finalizers.
------------------------------------------------------------------------
[2012-12-12 04:18:25] laruence@php.net
I agree.
gc doesn't record the refcount for zvals before calling destructor, so we have
no idea what have been changed during destructor calling.
but if we record that, a significant performance reduction will come
------------------------------------------------------------------------
[2012-12-10 13:32:54] dmitry@php.net
Unfortunately, it's not possible to fix the problem without significant complication of GC
algorithm that is going to increase memory consumption and to slow down PHP execution in general
(even without GC).
The original synchronous GC algorithm described at http://www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf
doesn't care about destructors. I think, that the concurrent algorithm described in the same
paper may fix the problem but with siginificant overhead. I wouldn't fix the problem in case
some cheaper workaround is found.
------------------------------------------------------------------------
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=63734
--
Edit this bug report at https://bugs.php.net/bug.php?id=63734&edit=1