Skip to content

Commit 4443c20

Browse files
[Cache] fix saving unrelated keys in recursive callback calls
1 parent c083e20 commit 4443c20

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@ public function testGet()
5959
$this->assertFalse($isHit);
6060
}
6161

62+
public function testRecursiveGet()
63+
{
64+
if (isset($this->skippedTests[__FUNCTION__])) {
65+
$this->markTestSkipped($this->skippedTests[__FUNCTION__]);
66+
}
67+
68+
$cache = $this->createCachePool(0, __FUNCTION__);
69+
70+
$v = $cache->get('k1', function () use (&$counter, $cache) {
71+
$v = $cache->get('k2', function () use (&$counter) { return ++$counter; });
72+
$v = $cache->get('k2', function () use (&$counter) { return ++$counter; });
73+
74+
return $v;
75+
});
76+
77+
$this->assertSame(1, $counter);
78+
$this->assertSame(1, $v);
79+
$this->assertSame(1, $cache->get('k2', function () { return 2; }));
80+
}
81+
6282
public function testGetMetadata()
6383
{
6484
if (isset($this->skippedTests[__FUNCTION__])) {

src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class PhpArrayAdapterTest extends AdapterTestCase
2323
{
2424
protected $skippedTests = [
2525
'testGet' => 'PhpArrayAdapter is read-only.',
26+
'testRecursiveGet' => 'PhpArrayAdapter is read-only.',
2627
'testBasicUsage' => 'PhpArrayAdapter is read-only.',
2728
'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.',
2829
'testClear' => 'PhpArrayAdapter is read-only.',

src/Symfony/Component/Cache/Traits/ContractsTrait.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ trait ContractsTrait
3131
}
3232

3333
private $callbackWrapper = [LockRegistry::class, 'compute'];
34+
private $computing = [];
3435

3536
/**
3637
* Wraps the callback passed to ->get() in a callable.
@@ -68,26 +69,27 @@ function (CacheItem $item, float $startTime, ?array &$metadata) {
6869
CacheItem::class
6970
);
7071

71-
return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata) {
72+
return $this->contractsGet($pool, $key, function (CacheItem $item, bool &$save) use ($pool, $callback, $setMetadata, &$metadata, $key) {
7273
// don't wrap nor save recursive calls
73-
if (null === $callbackWrapper = $this->callbackWrapper) {
74+
if (isset($this->computing[$key])) {
7475
$value = $callback($item, $save);
7576
$save = false;
7677

7778
return $value;
7879
}
79-
$this->callbackWrapper = null;
80+
81+
$this->computing[$key] = $key;
8082
$startTime = microtime(true);
8183

8284
try {
83-
$value = $callbackWrapper($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
85+
$value = ($this->callbackWrapper)($callback, $item, $save, $pool, function (CacheItem $item) use ($setMetadata, $startTime, &$metadata) {
8486
$setMetadata($item, $startTime, $metadata);
8587
});
8688
$setMetadata($item, $startTime, $metadata);
8789

8890
return $value;
8991
} finally {
90-
$this->callbackWrapper = $callbackWrapper;
92+
unset($this->computing[$key]);
9193
}
9294
}, $beta, $metadata);
9395
}

0 commit comments

Comments
 (0)