[Cache] fix memory leak when using PhpArrayAdapter

This commit is contained in:
Nicolas Grekas 2019-12-05 18:09:30 +01:00
parent 59126e0f9c
commit 4194c4c56d
7 changed files with 24 additions and 7 deletions

View File

@ -61,14 +61,13 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl
* fallback pool with this adapter only if the current PHP version is supported. * fallback pool with this adapter only if the current PHP version is supported.
* *
* @param string $file The PHP file were values are cached * @param string $file The PHP file were values are cached
* @param CacheItemPoolInterface $fallbackPool Fallback for old PHP versions or opcache disabled * @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit
* *
* @return CacheItemPoolInterface * @return CacheItemPoolInterface
*/ */
public static function create($file, CacheItemPoolInterface $fallbackPool) public static function create($file, CacheItemPoolInterface $fallbackPool)
{ {
// Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM if (\PHP_VERSION_ID >= 70000) {
if ((\PHP_VERSION_ID >= 70000 && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) || \defined('HHVM_VERSION')) {
if (!$fallbackPool instanceof AdapterInterface) { if (!$fallbackPool instanceof AdapterInterface) {
$fallbackPool = new ProxyAdapter($fallbackPool); $fallbackPool = new ProxyAdapter($fallbackPool);
} }

View File

@ -44,14 +44,14 @@ class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInt
* stores arrays in its latest versions. This factory method decorates the given * stores arrays in its latest versions. This factory method decorates the given
* fallback pool with this adapter only if the current PHP version is supported. * fallback pool with this adapter only if the current PHP version is supported.
* *
* @param string $file The PHP file were values are cached * @param string $file The PHP file were values are cached
* @param CacheInterface $fallbackPool A pool to fallback on when an item is not hit
* *
* @return CacheInterface * @return CacheInterface
*/ */
public static function create($file, CacheInterface $fallbackPool) public static function create($file, CacheInterface $fallbackPool)
{ {
// Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM if (\PHP_VERSION_ID >= 70000) {
if ((\PHP_VERSION_ID >= 70000 && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) || \defined('HHVM_VERSION')) {
return new static($file, $fallbackPool); return new static($file, $fallbackPool);
} }

View File

@ -62,6 +62,8 @@ class PhpArrayAdapterTest extends AdapterTestCase
protected function tearDown() protected function tearDown()
{ {
$this->createCachePool()->clear();
if (file_exists(sys_get_temp_dir().'/symfony-cache')) { if (file_exists(sys_get_temp_dir().'/symfony-cache')) {
FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache');
} }

View File

@ -37,6 +37,8 @@ class PhpArrayAdapterWithFallbackTest extends AdapterTestCase
protected function tearDown() protected function tearDown()
{ {
$this->createCachePool()->clear();
if (file_exists(sys_get_temp_dir().'/symfony-cache')) { if (file_exists(sys_get_temp_dir().'/symfony-cache')) {
FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache');
} }

View File

@ -56,6 +56,8 @@ class PhpArrayCacheTest extends CacheTestCase
protected function tearDown() protected function tearDown()
{ {
$this->createSimpleCache()->clear();
if (file_exists(sys_get_temp_dir().'/symfony-cache')) { if (file_exists(sys_get_temp_dir().'/symfony-cache')) {
FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache');
} }

View File

@ -43,6 +43,8 @@ class PhpArrayCacheWithFallbackTest extends CacheTestCase
protected function tearDown() protected function tearDown()
{ {
$this->createSimpleCache()->clear();
if (file_exists(sys_get_temp_dir().'/symfony-cache')) { if (file_exists(sys_get_temp_dir().'/symfony-cache')) {
FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache');
} }

View File

@ -28,6 +28,8 @@ trait PhpArrayTrait
private $values; private $values;
private $zendDetectUnicode; private $zendDetectUnicode;
private static $valuesCache = [];
/** /**
* Store an array of cached values. * Store an array of cached values.
* *
@ -107,6 +109,7 @@ EOF;
unset($serialized, $unserialized, $value, $dump); unset($serialized, $unserialized, $value, $dump);
@rename($tmpFile, $this->file); @rename($tmpFile, $this->file);
unset(self::$valuesCache[$this->file]);
$this->initialize(); $this->initialize();
} }
@ -119,6 +122,7 @@ EOF;
$this->values = []; $this->values = [];
$cleared = @unlink($this->file) || !file_exists($this->file); $cleared = @unlink($this->file) || !file_exists($this->file);
unset(self::$valuesCache[$this->file]);
return $this->pool->clear() && $cleared; return $this->pool->clear() && $cleared;
} }
@ -128,11 +132,17 @@ EOF;
*/ */
private function initialize() private function initialize()
{ {
if (isset(self::$valuesCache[$this->file])) {
$this->values = self::$valuesCache[$this->file];
return;
}
if ($this->zendDetectUnicode) { if ($this->zendDetectUnicode) {
$zmb = ini_set('zend.detect_unicode', 0); $zmb = ini_set('zend.detect_unicode', 0);
} }
try { try {
$this->values = file_exists($this->file) ? (include $this->file ?: []) : []; $this->values = self::$valuesCache[$this->file] = file_exists($this->file) ? (include $this->file ?: []) : [];
} finally { } finally {
if ($this->zendDetectUnicode) { if ($this->zendDetectUnicode) {
ini_set('zend.detect_unicode', $zmb); ini_set('zend.detect_unicode', $zmb);