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.