--- includes/bootstrap.inc.1.306	2009-09-21 09:07:07.000000000 +0100
+++ includes/bootstrap.inc	2009-10-02 22:41:15.000000000 +0100
@@ -752,9 +752,10 @@ function variable_del($name) {
  * Retrieve the current page from the cache.
  *
  * Note: we do not serve cached pages to authenticated users, or to anonymous
- * users when $_SESSION is non-empty. $_SESSION may contain status messages
- * from a form submission, the contents of a shopping cart, or other user-
- * specific content that should not be cached and displayed to other users.
+ * users when the current page request has been marked as being not cacheable.
+ * This happens, for example, when the user's $_SESSION contains status
+ * messages from a form submission that should not be cached and displayed
+ * to other users.
  *
  * @return
  *   The cache object, if the page was found in the cache, NULL otherwise.
@@ -768,12 +769,14 @@ function drupal_page_get_cache() {
 }
 
 /**
- * Determine the cacheability of the current page.
+ * Determine the cacheability of the current page request.
  *
  * @param $allow_caching
- *  Set to FALSE if you want to prevent this page to get cached.
+ *  Set to FALSE if you want to prevent this page from being cached, or to
+ *  prevent the current request being served from the cache.
  * @return
- *  TRUE if the current page can be cached, FALSE otherwise.
+ *  TRUE if the current page can be cached or served from the cache,
+ *  FALSE otherwise.
  */
 function drupal_page_is_cacheable($allow_caching = NULL) {
   $allow_caching_static = &drupal_static(__FUNCTION__, TRUE);
@@ -947,7 +950,7 @@ function drupal_send_headers($default_he
 }
 
 /**
- * Set HTTP headers in preparation for a page response.
+ * Set HTTP headers in preparation for an uncached page response.
  *
  * Authenticated users are always given a 'no-cache' header, and will fetch a
  * fresh page on every request. This prevents authenticated users from seeing
@@ -990,7 +993,7 @@ function drupal_page_header() {
 }
 
 /**
- * Set HTTP headers in preparation for a cached page response.
+ * Set HTTP headers for a cached or cacheable page response, and serve the page.
  *
  * The headers allow as much as possible in proxies and browsers without any
  * particular knowledge about the pages. Modules can override these headers
@@ -1025,7 +1028,7 @@ function drupal_serve_page_from_cache(st
 
   // If a cache is served from a HTTP proxy without hitting the web server,
   // the boot and exit hooks cannot be fired, so only allow caching in
-  // proxies if boot hooks are disabled. If the client send a session cookie,
+  // proxies if boot hooks are disabled. If the client sends a session cookie,
   // do not bother caching the page in a public proxy, because the cached copy
   // will only be served to that particular user due to Vary: Cookie, unless
   // the Vary header has been replaced or unset in hook_boot() (see below).
@@ -1056,7 +1059,7 @@ function drupal_serve_page_from_cache(st
   $default_headers['Last-Modified'] = gmdate(DATE_RFC1123, $cache->created);
 
   // HTTP/1.0 proxies does not support the Vary header, so prevent any caching
-  // by sending an Expires date in the past. HTTP/1.1 clients ignores the
+  // by sending an Expires date in the past. HTTP/1.1 clients ignore the
   // Expires header if a Cache-Control: max-age= directive is specified (see RFC
   // 2616, section 14.9.3).
   $default_headers['Expires'] = 'Sun, 19 Nov 1978 05:00:00 GMT';
@@ -1064,7 +1067,7 @@ function drupal_serve_page_from_cache(st
   drupal_send_headers($default_headers);
 
   // Allow HTTP proxies to cache pages for anonymous users without a session
-  // cookie. The Vary header is used to indicates the set of request-header
+  // cookie. The Vary header is used to indicate the set of request-header
   // fields that fully determines whether a cache is permitted to use the
   // response to reply to a subsequent request for a given URL without
   // revalidation. If a Vary header has been set in hook_boot(), it is assumed
@@ -1438,7 +1441,7 @@ function drupal_get_bootstrap_phase() {
 
 function _drupal_bootstrap($phase) {
   global $conf, $user;
-  static $cache;
+  static $cache, $hook_boot_invoked = FALSE;
 
   switch ($phase) {
 
@@ -1465,19 +1468,27 @@ function _drupal_bootstrap($phase) {
       drupal_block_denied(ip_address());
       // If there is no session cookie and cache is enabled (or forced), try
       // to serve a cached page.
-      if (!isset($_COOKIE[session_name()]) && $cache_mode == CACHE_NORMAL) {
-        // Make sure there is a user object because it's timestamp will be
-        // checked, hook_boot might check for anonymous user etc.
-        $user = drupal_anonymous_user();
+      if ($cache_mode == CACHE_NORMAL) {
+        if (isset($_COOKIE[session_name()])) {
+          // Need to check the user's session. Don't serve a cached response
+          // if user is logged in or if there are messages to display.
+          drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION, FALSE);
+        }
+        else {
+          // Make sure there is a user object because its timestamp will be
+          // checked, hook_boot might check for anonymous user etc.
+          $user = drupal_anonymous_user();
+        }
+        // If the skipping of the bootstrap hooks is not enforced, call
+        // hook_boot.
+        if (variable_get('page_cache_invoke_hooks', TRUE)) {
+          bootstrap_invoke_all('boot');
+          $hook_boot_invoked = TRUE;
+        }
         // Get the page from the cache.
         $cache = drupal_page_get_cache();
         // If there is a cached page, display it.
         if (is_object($cache)) {
-          // If the skipping of the bootstrap hooks is not enforced, call
-          // hook_boot.
-          if (variable_get('page_cache_invoke_hooks', TRUE)) {
-            bootstrap_invoke_all('boot');
-          }
           header('X-Drupal-Cache: HIT');
           drupal_serve_page_from_cache($cache);
           // If the skipping of the bootstrap hooks is not enforced, call
@@ -1521,7 +1532,9 @@ function _drupal_bootstrap($phase) {
       break;
 
     case DRUPAL_BOOTSTRAP_PAGE_HEADER:
-      bootstrap_invoke_all('boot');
+      if (!$hook_boot_invoked) {
+        bootstrap_invoke_all('boot');
+      }
       if (!$cache && drupal_page_is_cacheable()) {
         header('X-Drupal-Cache: MISS');
       }
--- includes/session.inc.1.71	2009-09-05 14:05:30.000000000 +0100
+++ includes/session.inc	2009-09-29 18:45:49.000000000 +0100
@@ -188,7 +188,9 @@ function drupal_session_initialize() {
     // anonymous users not use a session cookie unless something is stored in
     // $_SESSION. This allows HTTP proxies to cache anonymous pageviews.
     drupal_session_start();
-    if (!empty($user->uid) || !empty($_SESSION)) {
+    // Disable caching if user is logged in or if there are messages to
+    // display from a previous page request.
+    if (!empty($user->uid) || count(drupal_get_messages(NULL, FALSE)) > 0) {
       drupal_page_is_cacheable(FALSE);
     }
   }
