You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by je...@apache.org on 2005/08/11 19:38:20 UTC

svn commit: r231488 - in /httpd/httpd/trunk: CHANGES modules/cache/mod_cache.c

Author: jerenkrantz
Date: Thu Aug 11 10:38:18 2005
New Revision: 231488

URL: http://svn.apache.org/viewcvs?rev=231488&view=rev
Log:
Fix incorrectly served 304 responses when expired cache entity
is valid, but cache is unwritable and headers cannot be updated.

Submitted by: Colm MacCarthaigh <colm stdlib.net>
Reviewed by: Justin Erenkrantz

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/cache/mod_cache.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/CHANGES?rev=231488&r1=231487&r2=231488&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Thu Aug 11 10:38:18 2005
@@ -1,6 +1,10 @@
                                                         -*- coding: utf-8 -*-
 Changes with Apache 2.3.0
 
+  *) mod_cache: Fix incorrectly served 304 responses when expired cache
+     entity is valid, but cache is unwritable and headers cannot be
+     updated.  [Colm MacCarthaigh <colm stdlib.net>]
+
   *) mod_cache: Remove entities from the cache when re-validation
      receives a 404 or other content-no-longer-present error.
      [Rüdiger Plüm ruediger.pluem vodafone.com]

Modified: httpd/httpd/trunk/modules/cache/mod_cache.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/trunk/modules/cache/mod_cache.c?rev=231488&r1=231487&r2=231488&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/mod_cache.c (original)
+++ httpd/httpd/trunk/modules/cache/mod_cache.c Thu Aug 11 10:38:18 2005
@@ -682,7 +682,13 @@
         ap_cache_accept_headers(cache->handle, r, 1);
     }
 
-    /* Write away header information to cache. */
+    /* Write away header information to cache. It is possible that we are
+     * trying to update headers for an entity which has already been cached.
+     *
+     * This may fail, due to an unwritable cache area. E.g. filesystem full,
+     * permissions problems or a read-only (re)mount. This must be handled 
+     * later.
+     */
     rv = cache->provider->store_headers(cache->handle, r, info);
 
     /* Did we just update the cached headers on a revalidated response?
@@ -691,7 +697,7 @@
      * the same way as with a regular response, but conditions are now checked
      * against the cached or merged response headers.
      */
-    if (rv == APR_SUCCESS && cache->stale_handle) {
+    if (cache->stale_handle) {
         apr_bucket_brigade *bb;
         apr_bucket *bkt;
         int status;
@@ -715,12 +721,39 @@
         }
 
         cache->block_response = 1;
+
+        /* Before returning we need to handle the possible case of an
+         * unwritable cache. Rather than leaving the entity in the cache
+         * and having it constantly re-validated, now that we have recalled 
+         * the body it is safe to try and remove the url from the cache.
+         */
+        if (rv != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
+                         "cache: updating headers with store_headers failed. "
+                         "Removing cached url.");
+
+            rv = cache->provider->remove_url(cache->stale_handle, r->pool);
+            if (rv != OK) {
+                /* Probably a mod_disk_cache cache area has been (re)mounted 
+                 * read-only, or that there is a permissions problem. 
+                 */
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
+                     "cache: attempt to remove url from cache unsuccessful.");
+            }
+        }
+
         return ap_pass_brigade(f->next, bb);
     }
 
-    if (rv == APR_SUCCESS) {
-        rv = cache->provider->store_body(cache->handle, r, in);
+    if(rv != APR_SUCCESS) {
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
+                     "cache: store_headers failed");
+        ap_remove_output_filter(f);
+
+        return ap_pass_brigade(f->next, in);
     }
+
+    rv = cache->provider->store_body(cache->handle, r, in);
     if (rv != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
                      "cache: store_body failed");