Intermittent Blank Pages with WP-Cache

Intermittent Blank Pages with WP-Cache

WP-Cache helps my site run smoothly by storing copies of the web pages that are fetched most often from this site, which means that the WordPress system just needs to generate that page once. This has worked fine, except for a mysterious disappearing page problem that happens every once in a while.

A few of you have probably seen it: a visit to a popular page shows just the top-half of the page. I spent a little time debugging this tonight because I saw this problem occur three times with a popular post, which meant that a lot of people were unable to see it when they tried to. Well, no more!

WARNING! Geeky notes follow, so I don’t forget what I did.

Occasional Cache Corruption

Every once in a while, someone will send me a nice email telling me that a certain page is coming up “blank”, showing just the top-half of the web page with no text. What I usually do in this case is invalidate the cache in the WP-Cache options menu, and this fixes it. Unfortunately, it means all the cached files are also gone, which means the server has to rebuild all the cache files.

I eventually noticed that the problem files could be found by listing the cache contents under the WP-Cache Options panel, seeing which file is unusually small, and then deleting just that file. This tells WP-Cache to rebuild it next time someone requests it. In my case, if I see a posting file that is less than 9K, it’s probably screwed up. It appears that the file is truncated, chopped off at a certain point before the rest of WordPress has a chance to populate the page.

After today’s issues with my “Procrastinator’s Clock” page going under without warning, I decided to poke through the WP-Cache source code to see if I could insert an automatic check, so I wouldn’t have to worry about it.

Modifications to WP-Cache

The file wp-cache-phase1.php is that piece of WP-Cache that checks whether a particular URI has been cached already, serving the cached copy if it exists. Around line 35, I inserted the following:

...
foreach ($meta->headers as $header) {
    header($header);
}

// DS: start hack
$url = $meta->uri;
$size = @filesize($cache_file);
if ( $size < 9216 ) {
    error_log ("WPCache: $size < 9216, expiring $url");
    // write problem file
    $myFile = "/path/to/writeable/file/in/htdocs/wpcache.log";
    $fh = fopen($myFile, 'a') or die("can't open file");
    $stringData = file_get_contents($cache_file);
    fwrite($fh, "nn##n## Truncated File: ".$meta->uri." ($size) bytesnn");
    fwrite($fh, $stringData);
    fclose($fh);
    // tell WP to recreate cached file
    $file_expired = true;
    return;
}
// DS: end hack

$log = "<!-- Cached page served by WP-Cache -->n";
if ( !($content_size = @filesize($cache_file)) > 0 || $mtime < @filemtime($cache_file))
...

The code block marked DS: start hack is the new stuff. It grabs the url of the cached file being loaded out of the meta information stored with it and then sees how big the cached copy is. A good page on my site is always bigger than 9K, so if it’s LESS than that this means that the cached copy has been screwed up. This error is logged to the PHP Error Log AND the truncated output is written to another file called wpcache.log so I can analyze it later. The hack tells WordPress to re-generate the page by setting the “file expired” flag to true; WP-Cache will then recache it through a different module.

I’m hoping that this ensures that corrupted cache copies don’t stick around for hours as they’ve done in the past. Also, because I’m logging the errors, hopefully I’ll be able to figure out what the pattern is that causes this cache corruption to occur.

9 Comments

  1. seanrox 18 years ago

    Very interesting find. Just out of curiosity, what version of WP Cache are you running?

    On January 14, 2007 there was a new release, version 2.0.22 so maybe this was corrected?

    If not, you might want to let the developer know.

    ——-

  2. Dave Seah 18 years ago

    It’s version 2.0.21, but I’ve had this problem for at least a year and a half. I thought it had to do with the old server on Pair, and it seemed to go away on FutureQuest until I got LifeHacked a couple times. I started noticing it on the new service under heavy load. It might be related to comments being posted at the same time a page is being cached, but I have no data.

    I’ve seen some mentions about this intermittent problem posted here and there on Gallir’s site and around the Internet, but no hard data. I’m hoping that a few other people experiencing the problem, if it’s not just me, find this post so we can collectively figure out what’s going on. Until I can reproduce it, it isn’t a reportable bug.

    The new version 2.0.22 addresses something separate related to executing PHP in cached pages, which I don’t think would affect what I’m talking about. We’ll see! I’m able to gather data now, though at a slight performance penalty.

  3. Peter 18 years ago

    Now I’ve never used WP-cache, but does it implement file locking in the cache?  Is it a concurrency issue?  They’re not fun to debug…

  4. evariste 18 years ago

    David-this is just a guess, based on intuition. Check your php.ini file for a line that says max_execution_time = 30 and try doubling it. Pay attention to whether your wpcache.log file is growing as fast, or not. If it slows down, increase the max_execution_time some more. Here’s what I think is happening: when your site’s under heavy load, the php script that’s writing your cache files is contending for CPU and unfortunately running out of time to do its job, so it gets summarily executed in the middle of writing the file to disk.

  5. evariste 18 years ago

    If you’re on a shared host or don’t know where to find the php.ini, you can put a single line of php at the top of the wp-cache script that actually writes the cache file. set_time_limit(0); to give it as much time as it needs.

  6. Dave Seah 18 years ago

    Peter: I believe it does implement file locking. There’s reference to a “mutex” in the code. I haven’t traced the code though.

    Evariste: Ah…that’s an interesting theory! The problem happens very intermittently. During the day it does happen more often when the server is under heavier load. I’ll run my logging for a while longer to see what happens during the week, then try increasing the max_execution_time setting. My /etc/php.ini time is set to the default of 30 seconds. Thanks for the tip!!!

  7. Bob 18 years ago

    Try this… (copied from my webhosts wiki, i was having a similar problem, this may solve it…)

    Blank Pages

    If you have “blank pages” in WordPress with wp-cache turned on after you upgrade to PHP 5.1.2 – there is simple fix to solve the problem:-

    <ol>
    <li>Open /wp-content/plugins/wp-cache/wp-cache-phase2.php file* in your favourite text editor, where is the domain that you’re having troubles with EG: dreamhost.com/wp-content/plugins/wp-cache/wp-cache-phase2.php</li>
    <li>Alternatively if that file is not in that location for some reason you can issue this command to find it from the directory: find . -name wp-cache-phase2.php</li>
    <li>Find out wp_cache_ob_end function</li>
    <li>then inside that function find the line with: ob_end_clean(); (it should be line 219 or about)</li>
    <li>and finally replace that line with: ob_end_flush();</li>
    </ol>

  8. Dave Seah 18 years ago

    Bob: Thanks! I’m still on PHP4, not 5, so I’m pretty sure this doesn’t affect me. That particular bug produces blank pages all the time, not intermittently. I wonder what would happen though if I changed it still…?

  9. Dave Seah 18 years ago

    Update on max_execution_time: I upped it to 60 seconds, and didn’t see any improvement. I also did test a script that DID exceed 60 seconds of execution time, and the PHP log registered this as a PHP Fatal Error. However, I have never seen this before EVER, so I am thinking that the WP Cache intermittent failure is related to something else. Maybe it’s the DB timing out, or not being accessible?

    In the meantime, the hack above is at least keeping the site from displaying blank pages. It doesn’t add much overhead.