WordPress.org

Make WordPress Core

Opened 12 months ago

Last modified 7 days ago

#36455 new enhancement

Call opcache_reset() after plug-in, theme or core update

Reported by: nigro.simone Owned by:
Milestone: 4.8 Priority: normal
Severity: normal Version:
Component: Upgrade/Install Keywords: 2nd-opinion has-patch needs-testing
Focuses: Cc:

Description

wordpress it seem not reset Zend OpCache after plug-in, theme or core are updated.

For solve this issue i have set in the php.ini

opcache.validate_timestamps=1

all work correctly but validate_timestamps when it's enabled, PHP will check the file timestamp each request with a performance degradation. When it's disabled, PHP files are NEVER checked for updated code. When wordpress updating code, new code files can get mixed with old ones, the results are unknown. It's unsafe as hell.

Why wordpress not perform an opcache_reset() after each update if opcache is active and opcache.validate_timestamps is false?

Attachments (4)

36455.diff (1.2 KB) - added by asalce 3 months ago.
36455.2.diff (1.5 KB) - added by asalce 3 months ago.
36455.3.diff (1.5 KB) - added by asalce 3 months ago.
36455.4.diff (1.5 KB) - added by asalce 3 months ago.
Fixed a typo. No more coding at 2AM for me! :)

Download all attachments as: .zip

Change History (18)

#1 @dd32
12 months ago

  • Focuses performance removed
  • Keywords needs-patch 2nd-opinion added
  • Version 4.4.2 deleted

When running in an environment where PHP files are modified, using an opcode cache without some kind of filesystem monitoring is always going to be a bad idea - the opcode cache simply is not designed to be used within that environment.

I'm not against adding this, especially as it's more likely to be enabled in PHP 7, but this won't help at all for scenario's where a manual update is run, or WP-CLI (or other similar tools) are used to manage the updates.

It'd have to be run post plugin/theme/core update, on the plugin/theme editors, probably needs some way of being triggered by plugins too, etc.

#2 @JasWSInc
11 months ago

+1 for trying to automatically flush the OPcache (in core) after any theme/plugin update occurs. Perhaps on the shutdown action hook once the update is complete.

#3 @szepe.viktor
9 months ago

Please be aware that opcache.restrict_api might be set preventing execution.

This ticket was mentioned in Slack in #core by swissspidy. View the logs.


4 months ago

#5 @swissspidy
3 months ago

  • Milestone changed from Awaiting Review to 4.8
  • Type changed from feature request to enhancement

Adding this to the 4.8 milestone because we've seen many reports of broken sites after updates, all related to the OpCache not being cleared.

https://wordpress.org/support/topic/wordpress-4-7-fatal-error-cannot-redeclare-get_paged_template/ is just one example.

#6 follow-up: @JanR
3 months ago

Currently I'm looking into our opcache configuration settings in PHP 5.6 and 7, as we see more and more issues with WordPress updates lately too.

To ease updates you can use the upgrader_pre_install() hook, and perform a flush of the cache. I've created a little Must Use Plugin [1] for this (it cannot be done from within a plugin when using upgrader_pre_install()).

And don't forget OPcache's file path caches: http://php.net/manual/en/function.opcache-get-status.php.

As long as tools like WP-CLI use native WordPress core functionality, there should be no problem adding such a flush function to the core.

I'll get back when and if I found some valuable opcache settings administrators may need to set.

[1] https://www.saotn.org/wordpress-plugin-flush-php-opcache/

#7 in reply to: ↑ 6 @szepe.viktor
3 months ago

Replying to JanR:

As long as tools like WP-CLI use native WordPress core functionality, there should be no problem adding such a flush function to the core.

OPcache uses the process' shared memory thus Apache has no common OPcache with php-cli.

Drush uses a special URL to purge opcode cache.

#8 @JasWSInc
3 months ago

Regarding opcache.restrict_api. This INI setting, if not empty, contains a filesystem path that effectively becomes a whitelist, and therefore blacklists anything outside of the filesystem path given.

An example value for opcache.restrict_api would be something like:
opcache.restrict_api = /var/www/html/wp-content/plugins/xyz/

Which states that any PHP file that has a filesystem path that begins with /var/www/html/wp-content/plugins/xyz/ is whitelisted. Any that does not, is blacklisted.

So to check this in PHP (against the current __FILE__), use something like:

<?php
if(!ini_get('opcache.restrict_api') || stripos(__FILE__, ini_get('opcache.restrict_api')) === 0) {
    opcache_reset();
}

@asalce
3 months ago

#9 follow-up: @asalce
3 months ago

  • Keywords has-patch needs-testing added; needs-patch removed

I attached a new function wp_opcache_reset which should be called on "upgrader_process_complete" action. This should clear the OP Cache when ever the upgrade/update process is completed, I wasn't sure if this action is called for all updates (theme, plugin, wp core). Let me know if the attached patch fixes your issue.

#10 in reply to: ↑ 9 ; follow-up: @JanR
3 months ago

Replying to asalce:

I attached a new function wp_opcache_reset which should be called on "upgrader_process_complete" action. This should clear the OP Cache when ever the upgrade/update process is completed, I wasn't sure if this action is called for all updates (theme, plugin, wp core). Let me know if the attached patch fixes your issue.

A patch like this is something WordPress definitely needs. However, sometimes files are locked on the file system by the opcode cache (whether that's OPcache, WinCache or APCu doesn't matter), and the flush needs to be executed prior to updating.

Also, don't forget to remove, or invalidate, cached script paths:

<?php
foreach( $opcache_status['scripts'] as $key => $data ) {
        $dirs[dirname( $key )][basename( $key )] = $data;
        opcache_invalidate( $data['full_path'] , $force = true );
}

Reference http://php.net/manual/en/function.opcache-get-status.php.

#11 in reply to: ↑ 10 @asalce
3 months ago

Replying to JanR

So ultimately the reset / cache_invalidation needs to happen before the old files are deleted or overwritten? I can check it out tonight and see if I can pin-point this moment within the Upgrader Class.

@asalce
3 months ago

@asalce
3 months ago

#12 @asalce
3 months ago

The closest filter I found was 'upgrader_pre_download' which fires a few steps before the files are extracted from the zip file. I attached '36455.3.diff' with the proper use of the filter (ignore patch 2).

I also added some checks in the filter so:

  1. It only clears files within Wordpress' base dir
  2. Trigger only when validate_timestamps is not active

@JanR if we are invalidating each file, do we still need to call opcache_reset?

@dd32 brings up a good point about the external plugin updates. I am not sure there is much that can be done here, these tools should be made aware to call wp_opcache_reset manually. There is also the case when updates are ran via the filesystem (FTP for instance), which will completely by-pass all of Wordpress/PHP. My best guess is that certain hosts whom have validate_timestamps deactivated should take extra precaution when deploying to production, probably part of their build procedures.

Last edited 3 months ago by asalce (previous) (diff)

@asalce
3 months ago

Fixed a typo. No more coding at 2AM for me! :)

#13 @Garavani
4 weeks ago

This helped me out with my blank page issue after updating to wp 4.7.2. Thanks so much!!!
Anyhow I had to create a php.ini file first in the wp-admin directory.

#14 @pavelevap
7 days ago

What about plugin deactivation? It seems to me that scripts from deactivated plugins has the same problem (still in Opcache memory).

Note: See TracTickets for help on using tickets.