Make WordPress Core

Opened 13 years ago

Closed 13 years ago

#15881 closed defect (bug) (invalid)

wp_cache_get generates fatal error

Reported by: pixelgeek's profile pixelgeek Owned by:
Milestone: Priority: normal
Severity: critical Version: 3.0.3
Component: Cache API Keywords: $wp_object_cache, wp_cache_get cache.php
Focuses: Cc:

Description

There are timing issues in WP where some code in plugins, specifically wp super cache, make called to wp_cache_get before $wp_object_cache is initiated.

This generates a fatal error in php and can often send apache crashing.

This only occurs n wp_cache_get() and it seems as if the easiest solution is to check to see if $wp_object_cache is actually initaited and/or an object before calling its get() function.

Change History (19)

#1 @nacin
13 years ago

I would rather the plugin just fix the obviously incorrect call. They know enough to use the caching function, so they should also know to wait to use the object cache until it's actually instantiated.

#2 @pixelgeek
13 years ago

Maybe its just me but it seems like bad coding practice to assume good coding on the part of people using an API when a bad use of the API will result in the server possibly becoming unresponsive.

All that needs to happen is that the status of $wp_object_cache needs to be tested and then there is no problem.

There are a lot of people coding for WP and it seems that this is the easiest solution to this issue.

#3 @nacin
13 years ago

We shouldn't need to be defensive everywhere. It's not about the "server possibly becoming unresponsive" -- it's about the plugin flat out fatal erroring out. It's pretty obvious when that doesn't work.

Donncha has told me this is fixed in WP Super Cache trunk.

#4 @donncha
13 years ago

The problem is plugins (and Supercache here) using the caching system by accident *after* the caching object has been destroyed by PHP. Versions of PHP newer than 5.2 or so destroy objects during shutdown before the code in any shutdown callbacks runs.

I accidentally used get_option() when I called is_front_page() in the output buffer callback. It worked fine on my server but on other servers it obviously doesn't. That's why I didn't catch it before it was released.

This bit me in another way too, the plugin used a meta object to describe certain cached files. On some servers those cached files weren't served correctly and it took a long time to figure out why. I blogged about this ages ago and can dig up the post if anyone is interested.

Anyway, the problem is fixed now in trunk by caching out output of is_front_page() on init (or template_redirect, I can't remember) and using that cached variable.

#5 @nacin
13 years ago

That is pretty nasty, I'll admit.

I am curious if we avoided the register_shutdown_function() call to trigger __destruct manually, that this wouldn't occur. (Note, this is there for a reason despite it looking ridiculous, thanks to some PHP issues with certain versions.)

#6 @pixelgeek
13 years ago

But even if WP Super Cache fixes their usage it still is possible for other plugins and coders to run into the same issue.

Maybe a straight test isn't necessarily the way to fix it (I'll admit that my php skills aren't good enough to be commenting in any depth) but I think that there needs to be some way to avoid having the caching code access the object if there is the possibility that it won't be there.

Especially when we're dealing with something as screwy as timing issues. As Donncha notes this doesn't happen consistently across platforms or php instances so it might not even be something that a dev might see on their own system and yet have it crop up on other sites.

#7 @nacin
13 years ago

This is a very rare condition. Basically, it can only occur on shutdown. From the moment these functions initially exist, $wp_object_cache is instantiated.

We'll need more information to figure out exactly what is going on at the core PHP and object destruction level to figure out what we need to do to prevent this.

Ideally, the cache should always exist if necessary. If it's getting destroyed too early, then that's the problem, and the fatal error is simply the symptom.

#8 @pixelgeek
13 years ago

What exactly do you mean by "shutdown"?

#9 @nacin
13 years ago

PHP shutdown: http://us.php.net/manual/en/function.register-shutdown-function.php

Donncha: "Shutdown functions are called after closing all opened output buffers" according to that PHP page. Interesting.

#10 follow-up: @pixelgeek
13 years ago

I'm running into a very similar problem with $wpdb in the functions.php code on line 410.

Can anyone suggest a good way to track down the source of the call? I'd rather patch a plugin if I can

#11 in reply to: ↑ 10 @SergeyBiryukov
13 years ago

Have you tried debug_backtrace()?

#12 @pixelgeek
13 years ago

I'm getting these error reports from my syslog file. I should have been more specific. I need to see what I can do in the php.ini file or on the server to track the errors since I have no idea what page is actually generating this.

I'd try to do something locally but my dev server doesn't generate these errors or at least doesn't do so frequently enough for me to try to track them locally.

#13 @pixelgeek
13 years ago

I've actually entered the new error as a separate bug as it appears that only the wp codebase is accessing the function and not a plugin

#14 @pixelgeek
13 years ago

Disabling WP Super Cache solves the problem.

If it makes any difference, this issue became much more problematic after I updated to 3.03

#15 @tomarq
13 years ago

I'm having a similar problem when using wp-hive 0.6.1 and WordPress 3.1-RC1-17163. WP hive uses db.php to to adjust some settings and it checks to see if the plugin is active with "get_option('active_plugins');".

db.php is loaded (and therefore the plugin starts) in wp-settings.php line 73, but the cache isn't started until wp-settings.php line 79; this is why wp-hive fails. The WP core functiion get_option won't work here.

This is related to #14508 I believe now that db.php is loaded in wp-load.php instead of functions.php.

WP2.9.2 and WP3.0.3 loaded db.php in functions.php, WP3.1RC loads it in load.php so this plugin doesn't have access to core functions that it previously did... get_option.

Last edited 13 years ago by tomarq (previous) (diff)

#16 @nacin
13 years ago

3.0 used load.php too. That's not the culrpit, it wasn't a functional change.

PHP version?

#17 @tomarq
13 years ago

PHP 5.3.2

(previous comment mentioned wp-load lines 73 and 79, but that was in error, it's wp-settings lines 73 and 79)

I've tried moving wp_start_object_cache(); to before require_wp_db(); and the original error is solved, but I get SQL errors because get_option doesn't yet have table names/prefixes. Moving wp_set_wpdb_vars(); up to get prefixes obviously fails because require_wp_db hasn't been called yet. So, it's a catch 22 (at least as compares to how WP previously worked).

I can see how very few plugins use db.php to get started early (caches and things like hive) but, a hook after the database is set up, before WP really gets going, could be useful. Something in wp-setting.php around about line 94:

// Stop most of WordPress from being loaded if we just want the basics.
if ( SHORTINIT )
        return false;

POST_INIT_HOOK_HERE?

seems like a good spot.

Last edited 13 years ago by tomarq (previous) (diff)

#18 @pixelgeek
13 years ago

While moving some sites around today I realized that the issue isn't the server config. I have another domain on the site that use WP Super Cache without any errors at all.

Is the amount of traffic on a site a possible culprit? The site that has issues gets about 500,000 pageviews a month while the other site gets 100 a month.

#19 @westi
13 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to invalid
  • Status changed from new to closed

I've read through this and there is no actionable thing for core here at the moment.

Closing.

Note: See TracTickets for help on using tickets.