Updating addons via CLI doesn't invalidate opcode cache

K a M a L

Well-known member
Affected version
2.2.latest
I noticed that template modifications are not applied when updating addons via CLI because opcache.enable_cli default value is 0
Xenforo needs to enqueue a job to invalidate opcache after addon install/upgrade
 
With opcache.enable_cli being set to 0, it means the CLI doesn't use the OPcache. So invalidating the cache isn't going to change anything for CLI. Even if you change that to use the opcache via the CLI, it's still not going to invalidate the cache for you automatically if a file get written (writing a PHP file is a completely different thing than executing a PHP file).

If the opcode cache isn't updating when files change, you probably changed the opcache.revalidate_freq option from it's default of 2. The issue with setting opcache.revalidate_freq to 0 (never check if a file has changed) is that there are a TON of ways PHP files can change, so trying to account for all of those manually (making sure you invalidate the cache any time you copy a PHP file for example) is an almost impossible task.

If you really don't want to check if files have changed, you could raise it to 60 seconds or something. That way in a worst case scenario where you forgot to invalidate the cache manually for something, it would take a maximum of 60 seconds before the new PHP file showed up.

That being said, if you override the opcache to not revalidate file changes (it does by default), you are going to need to make sure you invalidate the cache on your end when you want to (since you've disabled it's ability to do it automatically by default).
 
With opcache.enable_cli being set to 0, it means the CLI doesn't use the OPcache. So invalidating the cache isn't going to change anything for CLI. Even if you change that to use the opcache via the CLI, it's still not going to invalidate the cache for you automatically if a file get written (writing a PHP file is a completely different thing than executing a PHP file).

If the opcode cache isn't updating when files change, you probably changed the opcache.revalidate_freq option from it's default of 2. The issue with setting opcache.revalidate_freq to 0 (never check if a file has changed) is that there are a TON of ways PHP files can change, so trying to account for all of those manually (making sure you invalidate the cache any time you copy a PHP file for example) is an almost impossible task.

If you really don't want to check if files have changed, you could raise it to 60 seconds or something. That way in a worst case scenario where you forgot to invalidate the cache manually for something, it would take a maximum of 60 seconds before the new PHP file showed up.

That being said, if you override the opcache to not revalidate file changes (it does by default), you are going to need to make sure you invalidate the cache on your end when you want to (since you've disabled it's ability to do it automatically by default).
you are right .. I have opcache.revalidate_freq set to 0 .. but Xenforo tries to invalidate code cache when writing files and it works fine when installing addons via web interface .. I think this needs to be consistent
PHP:
if ($type == 'code-cache')
        {
            $fs = $event->getFilesystem();
            if ($fs instanceof \League\Flysystem\Filesystem)
            {
                $adapter = $fs->getAdapter();
                if ($adapter instanceof \XF\LocalFsAdapter)
                {
                    foreach ($files AS $file)
                    {
                        $filePath = $adapter->applyPathPrefix($file);
                        \XF\Util\Php::invalidateOpcodeCache($filePath);
                    }
                }
            }
        }
 
Honestly I didn't know XenForo was trying to handle opcache invalidations for templates, widgets and phrases (what's stored in code-cache). I guess if they want to try and handle it, it would be appropriate to do it on the CLI too.

To me, it still doesn't seem like a great idea though. Normal operating systems are storing file changes in-memory cache at the kernel level, so checking if a file changed, isn't actually causing a disk I/O and there's a whole lot of ways a PHP file could be changed (for example simply uploading new PHP files manually which isn't going to trigger any sort of XenForo code simply by uploading to the server). Like right now are you needing to manually invalidate the cache (or restart PHP-FPM) if you upload files for a new version of XenForo?
 
Honestly I didn't know XenForo was trying to handle opcache invalidations for templates, widgets and phrases (what's stored in code-cache). I guess if they want to try and handle it, it would be appropriate to do it on the CLI too.

To me, it still doesn't seem like a great idea though. Normal operating systems are storing file changes in-memory cache at the kernel level, so checking if a file changed, isn't actually causing a disk I/O and there's a whole lot of ways a PHP file could be changed (for example simply uploading new PHP files manually which isn't going to trigger any sort of XenForo code simply by uploading to the server). Like right now are you needing to manually invalidate the cache (or restart PHP-FPM) if you upload files for a new version of XenForo?
Yes, I manually update opcache after uploading files .. I know performance boost due to disabling opcache.validate_timestamps is minimal but I'm fine with it .. I don't have a big trouble due to this issue right now and not looking for immediate solution. just wanted to log it in case Xenforo team would consider resolving it anytime in the future.
 
Opcode memory cache is not shared by different SAPIs (like CLI, CGI, FPM, LSAPI, etc.) so there simply isn't a direct way to invalidate opcache from CLI.

Depending on the setup / environment there might not even be a process running the "web" SAPI on the same machine/ container running CLI.

One approach (that should work in many cases, but not necessarily every case) could be to use the XenForo API, eg. send an API request to the webserver from CLI.
 
Top Bottom