Bug #77478 [Com]: opcache_reset() does not reset an opcache.file_cache-based cache

From: Date: Fri, 25 Jan 2019 20:58:55 +0000
Subject: Bug #77478 [Com]: opcache_reset() does not reset an opcache.file_cache-based cache
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-219217@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=77478&edit=1

 ID:                 77478
 Comment by:         post at minhost dot no
 Reported by:        anders dot henke at 1und1 dot de
 Summary:            opcache_reset() does not reset an
                     opcache.file_cache-based cache
 Status:             Open
 Type:               Bug
 Package:            opcache
 Operating System:   Linux
 PHP Version:        7.3.1
 Block user comment: N
 Private report:     N

 New Comment:

To me this is not a bug. We depend on opcache.file_cache as a second level fallback cache used when
PHP-FPM is restarted, so that even when opcache in memory is empty, the first hit will be from file
cache.

If opcache_reset is changed so that the files in opcache.file_cache is emptied every time PHP-FPM is
restarted, that would be very bad, as it would defeat the purpose of having opcache.file_cache as
second level fallback cache.

Also you can set opcache.revalidate_freq=0 (like we have done), so that the timestamp is checked for
every updates on every request, that way you will never get code from outdated cache objects.

Also, if you update PHP every month with a new PHP version, then the entire directory for file_cache
get a new name/number, and you simply delete the old directory after each PHP upgrade.

I ask that the current behavior is not changed, as we very much depend on having opcache.file_cache
as a second level fallback cache, so that first request when opcache in memory is empty, is from the
opcache.file_cache


Previous Comments:
------------------------------------------------------------------------
[2019-01-17 12:28:37] anders dot henke at 1und1 dot de

Description:
------------
From PHP 7.0 on, PHP's opcache includes a file-cache as an optional overflow mechanism and
optionally as the only kind of opcache storage (opcache.file_cache_only=1). The later is interesting
in CGI-mode, where shared memory does not survive a single PHP run.

PHP's opcache does provide a function opcache_reset() to "reset the entire opcode cache.
After calling opcache_reset(), all scripts will be reloaded and reparsed the next time they are
hit.".

This function may be called explicitely (e.g. during software deployment) to clear any caches and
remove accumulated stale cache objects who are no longer being accessed. Whenever a file-based
opcache storage is being added to Opcache, opcache_reset() does only reset a shared memory-based
opcache, but does not reset any file-based opcache storage.

In a performance-optimized setup, a user may use shared-memory-based opcache with file-based opcache
storage as a fallback, disable automatic revalidation and manually perform opcache_reset() during
the deployment process. In such a situation, opcache_reset() returns true and restarts the shared
memory-based storage, but does not remove any objects from the file-based opcache storage. This
possibly might result in running code from outdated cache objects.

Test script:
---------------
php.ini:
---cut
zend_extension=opcache.so;
opcache.enable=1;
opcache.revalidate_freq=180;
opcache.validate_timestamps=2;
opcache.file_cache=/var/tmp/opcache;
opcache.file_cache_only=1;
---cut

clear.php:

---cut
<pre>
<?php
echo "**Before Clear Opcache:\n";
system('ls -lRt ' . ini_get('opcache.file_cache'));

echo "\n\n**Clear Opcache: ";
var_dump(opcache_reset());
echo "\n";

echo "**After Clear Opcache:\n";
system('ls -lRt ' . ini_get('opcache.file_cache'));

?>
</pre>
---cut

Expected result:
----------------
http://php.net/manual/en/function.opcache-reset.php
states "This function resets the entire opcode cache. After calling opcache_reset(), all
scripts will be reloaded and reparsed the next time they are hit.

According to my reading, "reset the entire opcache" does also include the file-based
opcache.

In my test script above, the actual content "before" and "after" opcache_reset()
stays the same.

Actual result:
--------------
opcache_reset() does not affect a file-based opcache at all and only restarts the
shared-memory-based opcache.

In a file_cache_only-configuration, opcache_reset() does not reset the file-based opcache, but
returns "false", which should only happen when opcache is disabled.
According to phpinfo(), opcache is enabled and running.

In a overflow/fallback configuration, opcache_reset() does return true, but will only restart the
shared memory storage and not reset any file-based opcache storage. Depending on the overall
configuration, this might result in running cached but outdated code. Such an issue has also been
reported in bug #75670.


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=77478&edit=1


Thread (6 messages)

« previous php.bugs (#219217) next »