You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bugs@httpd.apache.org by bu...@apache.org on 2006/06/05 04:11:47 UTC

DO NOT REPLY [Bug 30370] - Pages cached in more than one cache remain stale although it is revalidated.

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG�
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=30370>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND�
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=30370





------- Additional Comments From tyamadajp@list.rakugaki.org  2006-06-05 02:11 -------
Though not sure if it is the same cause, I'm having exactly the same issue and 
I think I have tracked down the bug. I've reviewed the code in latest snapshot 
and believe this bug still exists both in 2.0 and 2.2 (I have verified it with 
2.0 tree). Also, this could also be a bug in mod_mem_cache.c.

The cause of this bug is that cached entry never gets removed from cache 
repository maintained by mod_*_cache. There's a issue in 
cache_storage.c:cache_select_url method that incorrectly(?) handles cache-
>stale_handle. Here's the code:

  fresh = ap_cache_check_freshness(h, r);
  if (!fresh) {
    if (info && info->etag) {
       ...
       cache->stale_handle = h;
    }
    else if (info && info->lastmods) {
      ...
      cache->stale_handle = h;
    }
    return DECLINED;
  }
  ...
  cache->handle = h;

As you can see, even when cache has expired, there's a case when cache-
>stale_handle does not get set. Because of this, following part of the code in 
mod_cache.c:cache_save_filter is never executed:

  if (cache->stale_handle) {
    if (r->status == HTTP_NOT_MODIFIED) {
      ...
    }
    else {
      /* Oh, well.  Toss it. */
      cache->provider->remove_entity(cache->stale_handle);
      /* Treat the request as if it wasn't conditional. */
      cache->stale_handle = NULL;
    }
  }

So when cache->stale_handle is not set, above remove_entity is never called, 
meaning (expired) cache remains in cache repository.

Now, because obsolete cache remains, following code in 
mod_cache.c:cache_save_filter fails with mod_mem_cache:

  /* no cache handle, create a new entity */
  if (!cache->handle) {
    rv = cache_create_entity(r, url, size);
    ...
  }

  if (rv != OK) {
    /* Caching layer declined the opportunity to cache the response */
    ...

Looking into mod_mem_cache.c:create_entity, there's a following code:

  tmp_obj = (cache_object_t *) cache_find(sconf->cache_cache, key);
  ...
  if (tmp_obj) {
    /* This thread collided with another thread loading the same object
     * into the cache at the same time. Defer to the other thread which
     * is further along.
     */
    cleanup_cache_object(obj);
    return DECLINED;
  }

So mod_mem_cache.c:create_entity (incorrectly) returns a "thread conflict" 
error when obsolete cache remains in cache repository. And due to this return 
code, mod_cache.c:cache_save_filter skips caching.

To fix (or workaround) this issue, cache_storage.c:cache_select_url can be 
fixed as follows:

  fresh = ap_cache_check_freshness(h, r);
  if (!fresh) {
    cache->stale_headers = apr_table_copy(r->pool, r->headers_in);
    cache->stale_handle = h;

    /* Make response into a conditional */
    /* FIXME: What if the request is already conditional? */
    if (info && info->etag) {
      /* if we have a cached etag */
      apr_table_set(r->headers_in, "If-None-Match", info->etag);
    }
    else if (info && info->lastmods) {
      /* if we have a cached Last-Modified header */
      apr_table_set(r->headers_in, "If-Modified-Since", info->lastmods);
    }
    return DECLINED;
  }

Similar fix can be done with Apache 2.2 as well.

I'm now looking into caching behavior of mod_disk_cache.c, as unlike 
mod_mem_cache.c, it seems it does not check for thread-level conflict.
After all review is done, I'll send in a patch.


-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org