Index: includes/bootstrap.inc
===================================================================
--- includes/bootstrap.inc	(revision 3087)
+++ includes/bootstrap.inc	(working copy)
@@ -106,6 +106,12 @@
 define('DRUPAL_AUTHENTICATED_RID', 2);
 
 /**
+ * The maximum time to allow for a lock to be held when rebuilding a page for 
+ * the page cache -- this is to prevent stale locks from aborted sessions.
+ */
+define('CACHE_REBUILD_MAX', 5);
+
+/**
  * Start the timer with the specified name. If you start and stop
  * the same timer multiple times, the measured intervals will be
  * accumulated.
@@ -473,12 +479,23 @@
   if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_set_message()) == 0) {
     $cache = cache_get($base_root . request_uri(), 'cache_page');
 
+    // Check if the currently cached page was created before the cache was
+    // last flushed.  If so, try to rebuild it.
+    if (is_object($cache) && $cache->timestamp < variable_get('cache_page_clear', 0)) {
+      $lock = cache_get($base_root . request_uri(), 'cache_lock');
+      if (!$lock) {
+        // Grab the lock and rebuild the web page.
+        cache_set($base_root . request_uri(), 'cache_lock', time(), time() + CACHE_REBUILD_MAX);
+        $cache = NULL;
+      }
+    }
+
     if (empty($cache)) {
       ob_start();
     }
   }
 
-  return $cache;
+  return $cache->contents;
 }
 
 /**
Index: includes/common.inc
===================================================================
--- includes/common.inc	(revision 3087)
+++ includes/common.inc	(working copy)
@@ -1894,8 +1894,10 @@
   global $user, $base_root;
 
   if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_get_messages(NULL, FALSE)) == 0) {
+    $data = NULL;
     // This will fail in some cases, see page_get_cache() for the explanation.
-    if ($data = ob_get_contents()) {
+    if ($data->contents = ob_get_contents()) {
+      $data->timestamp = time();
       $cache = TRUE;
       if (function_exists('gzencode')) {
         // We do not store the data in case the zlib mode is deflate.
@@ -1904,14 +1906,16 @@
           $cache = FALSE;
         }
         else if (zlib_get_coding_type() == FALSE) {
-          $data = gzencode($data, 9, FORCE_GZIP);
+          $data->contents = gzencode($data->contents, 9, FORCE_GZIP);
         }
         // The remaining case is 'gzip' which means the data is
         // already compressed and nothing left to do but to store it.
       }
       ob_end_flush();
-      if ($cache && $data) {
+      if ($cache && is_object($data) && $data->contents) {
         cache_set($base_root . request_uri(), 'cache_page', $data, CACHE_TEMPORARY, drupal_get_headers());
+        // Clear lock that prevented multiple requests rebuilding the same page.
+        cache_clear_all($base_root . request_uri(), 'cache_lock');
       }
     }
   }
Index: sites/default/modules/memcache/memcache.inc
===================================================================
--- sites/default/modules/memcache/memcache.inc	(revision 3087)
+++ sites/default/modules/memcache/memcache.inc	(working copy)
@@ -80,6 +80,13 @@
  *   match. If '*' is given as $cid, the table $table will be emptied.
  */
 function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
+  // Special handling for the page cache.  Rather than flushing this table, we
+  // update a variable.  When pages are in high demand, this allows us to serve
+  // the old cached version while an updated version is being created.
+  if ($table == 'cache_page') {
+    variable_set('cache_page_clear', time());
+    return;
+  }
   // Memcache logic is simpler because memcache doesn't have a minimum cache
   // lifetime consideration (it handles it internally), and doesn't support
   // wildcards.
