Closed
Description
Description
In the code below, var_dump(array_keys($analysingMap->valueWithOwnerCountByIndex))
called twice prints different results even if the value is not changed between the calls.
I did my best to create a minimal repro. It seems the issue is present when weak references and destructor is used.
When opcache and/or GC is disabled, the issue is still present. It seems there is some allocation/refcounting issue in destructors.
repro: https://3v4l.org/h7ZER
<?php
class WeakMap2
{
private array $weakRefs = [];
private array $values = [];
public function offsetSet($object, $value) : void
{
$id = spl_object_id($object);
$this->weakRefs[$id] = \WeakReference::create($object);
$this->values[$id] = $value;
}
}
class WeakAnalysingMapRepro
{
/* private */ public array $valueWithOwnerCountByIndex = [];
private WeakMap2 $ownerDestructorHandlers;
public function __construct()
{
$this->ownerDestructorHandlers = new WeakMap2();
$this->addKeyOwner(new \DateTime());
}
protected function addKeyOwner(object $owner)
{
$handler = new class($this) {
private \WeakReference $weakAnalysingMap;
public function __construct(WeakAnalysingMapRepro $analysingMap)
{
$this->weakAnalysingMap = \WeakReference::create($analysingMap);
}
public function __destruct()
{
$analysingMap = $this->weakAnalysingMap->get();
var_dump(array_keys($analysingMap->valueWithOwnerCountByIndex));
\Closure::bind(static function () use ($analysingMap) {
var_dump(array_keys($analysingMap->valueWithOwnerCountByIndex));
}, null, WeakAnalysingMapRepro::class)();
}
public function addReference($index): void
{
$analysingMap = $this->weakAnalysingMap->get();
$analysingMap->valueWithOwnerCountByIndex[$index] = true;
}
};
$this->ownerDestructorHandlers->offsetSet($owner, $handler);
$handler->addReference(10);
}
}
$map = new WeakAnalysingMapRepro();
unset($map);
echo 'DONE';
Resulted in this output:
array(1) {
[0]=>
int(10)
}
array(1) {
[0]=>
string(12) "analysingMap"
}
DONE
But I expected this output instead:
array(1) {
[0]=>
int(10)
}
array(1) {
[0]=>
int(10)
}
DONE
PHP Version
any (tested 7.4, 8.1, 8.3, master)
Operating System
any (tested Windows, Linux)