Opened 6 months ago

Last modified 4 months ago

#22661 new defect (bug)

Allow object caches to degrade gracefully

Reported by: markjaquith Owned by:
Priority: normal Milestone: Awaiting Review
Component: Cache Version:
Severity: normal Keywords:
Cc: scribu, aaroncampbell

Description

Because of the way object caches are loaded, if a custom object cache can't run (say, Memcached or APC is not actually installed), it cannot gracefully degrade to the built-in object cache.

Witness this code in wp_start_object_cache():

 	if ( ! function_exists( 'wp_cache_init' ) ) {
		if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
			require_once ( WP_CONTENT_DIR . '/object-cache.php' );
			$_wp_using_ext_object_cache = true;
		} else {
			require_once ( ABSPATH . WPINC . '/cache.php' );
			$_wp_using_ext_object_cache = false;
		}
		$first_init = true;
	} else if ( !$_wp_using_ext_object_cache && file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
		// Sometimes advanced-cache.php can load object-cache.php before it is loaded here.
		// This breaks the function_exists check above and can result in $_wp_using_ext_object_cache
		// being set incorrectly. Double check if an external cache exists.
		$_wp_using_ext_object_cache = true;
	}

So a custom object cache is loaded. If it wants to bail and defer to the built in object caching, it can do that by doing the include itself. But then WordPress sets $_wp_using_ext_object_cache = true; after that require. So WordPress thinks it is using an external object cache when it's actually not. This leads to oddness.

This can sometimes be hacked around by adding a callback to the very first WP action available that sets $_wp_using_ext_object_cache = false;, but that has issues: calls to the object cache might be made before that code can run, and add_action() is not always available at that point (because some advanced-cache.php drop-ins load the object cache really early. See Batcache.

Proposed solution: change the order of the require_once() and the setting of $_wp_using_ext_object_cache. That way, the external object cache can override the variable.

Change History (3)

this is mildly related: #21401

  • Cc scribu added
  • Cc aaroncampbell added
Note: See TracTickets for help on using tickets.