Skip to content

Commit

Permalink
bug #32236 [Cache] work aroung PHP memory leak (nicolas-grekas)
Browse files Browse the repository at this point in the history
This PR was merged into the 4.2 branch.

Discussion
----------

[Cache] work aroung PHP memory leak

| Q             | A
| ------------- | ---
| Branch?       | 4.2
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #32220
| License       | MIT
| Doc PR        | -

Works around  https://bugs.php.net/76982, as identified by @goetas in the linked issue.

Commits
-------

5d55b91 [Cache] work aroung PHP memory leak
  • Loading branch information
nicolas-grekas committed Jun 28, 2019
2 parents 5edac83 + 5d55b91 commit 3f16506
Showing 1 changed file with 48 additions and 9 deletions.
57 changes: 48 additions & 9 deletions src/Symfony/Component/Cache/Traits/PhpFilesTrait.php
Expand Up @@ -50,12 +50,15 @@ public function prune()
{
$time = time();
$pruned = true;
$getExpiry = true;

set_error_handler($this->includeHandler);
try {
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
try {
list($expiresAt) = include $file;
if (\is_array($expiresAt = include $file)) {
$expiresAt = $expiresAt[0];
}
} catch (\ErrorException $e) {
$expiresAt = $time;
}
Expand Down Expand Up @@ -87,15 +90,21 @@ protected function doFetch(array $ids)
$values = [];

begin:
$getExpiry = false;

foreach ($ids as $id) {
if (null === $value = $this->values[$id] ?? null) {
$missingIds[] = $id;
} elseif ('N;' === $value) {
$values[$id] = null;
} elseif ($value instanceof \Closure) {
$values[$id] = $value();
} else {
} elseif (!\is_object($value)) {
$values[$id] = $value;
} elseif (!$value instanceof LazyValue) {
// calling a Closure is for @deprecated BC and should be removed in Symfony 5.0
$values[$id] = $value();
} elseif (false === $values[$id] = include $value->file) {
unset($values[$id], $this->values[$id]);
$missingIds[] = $id;
}
if (!$this->appendOnly) {
unset($this->values[$id]);
Expand All @@ -108,10 +117,18 @@ protected function doFetch(array $ids)

set_error_handler($this->includeHandler);
try {
$getExpiry = true;

foreach ($missingIds as $k => $id) {
try {
$file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
list($expiresAt, $this->values[$id]) = include $file;

if (\is_array($expiresAt = include $file)) {
[$expiresAt, $this->values[$id]] = $expiresAt;
} elseif ($now < $expiresAt) {
$this->values[$id] = new LazyValue($file);
}

if ($now >= $expiresAt) {
unset($this->values[$id], $missingIds[$k]);
}
Expand Down Expand Up @@ -140,7 +157,13 @@ protected function doHave($id)
set_error_handler($this->includeHandler);
try {
$file = $this->files[$id] ?? $this->files[$id] = $this->getFile($id);
list($expiresAt, $value) = include $file;
$getExpiry = true;

if (\is_array($expiresAt = include $file)) {
[$expiresAt, $value] = $expiresAt;
} elseif ($this->appendOnly) {
$value = new LazyValue($file);
}
} catch (\ErrorException $e) {
return false;
} finally {
Expand Down Expand Up @@ -189,13 +212,16 @@ protected function doSave(array $values, $lifetime)
}

if (!$isStaticValue) {
$value = str_replace("\n", "\n ", $value);
$value = "static function () {\n\n return {$value};\n\n}";
// We cannot use a closure here because of https://bugs.php.net/76982
$value = str_replace('\Symfony\Component\VarExporter\Internal\\', '', $value);
$value = "<?php\n\nnamespace Symfony\Component\VarExporter\Internal;\n\nreturn \$getExpiry ? {$expiry} : {$value};\n";
} else {
$value = "<?php return [{$expiry}, {$value}];\n";
}

$file = $this->files[$key] = $this->getFile($key, true);
// Since OPcache only compiles files older than the script execution start, set the file's mtime in the past
$ok = $this->write($file, "<?php return [{$expiry}, {$value}];\n", self::$startTime - 10) && $ok;
$ok = $this->write($file, $value, self::$startTime - 10) && $ok;

if ($allowCompile) {
@opcache_invalidate($file, true);
Expand Down Expand Up @@ -241,3 +267,16 @@ protected function doUnlink($file)
return @unlink($file);
}
}

/**
* @internal
*/
class LazyValue
{
public $file;

public function __construct($file)
{
$this->file = $file;
}
}

0 comments on commit 3f16506

Please sign in to comment.