diff options
author | Bill Stoddard <stoddard@apache.org> | 2002-06-15 16:49:19 +0000 |
---|---|---|
committer | Bill Stoddard <stoddard@apache.org> | 2002-06-15 16:49:19 +0000 |
commit | fabbd581969751e3030b7bf40afc3aef6d122e9b (patch) | |
tree | 64bae1ba7ac487ab0f8d28eeee336b1a8cd850c3 /modules | |
parent | e397f79a00d14c7fdace497538a9c295e08fa332 (diff) | |
download | httpd-fabbd581969751e3030b7bf40afc3aef6d122e9b.tar.gz |
Close race condition cleaning up cache entry.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95698 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules')
-rw-r--r-- | modules/experimental/mod_mem_cache.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/modules/experimental/mod_mem_cache.c b/modules/experimental/mod_mem_cache.c index 989ee4f48e..d3b3ae5c63 100644 --- a/modules/experimental/mod_mem_cache.c +++ b/modules/experimental/mod_mem_cache.c @@ -192,12 +192,37 @@ static const char* memcache_cache_get_key(void*a) } /** * callback to free an entry - * XXX: just call cleanup_cache_object ? + * There is way too much magic in this code. Right now, this callback + * is only called out of cache_insert() which is called under protection + * of the sconf->lock, which means that we do not (and should not) + * attempt to obtain the lock recursively. */ static void memcache_cache_free(void*a) { cache_object_t *obj = (cache_object_t *)a; - cleanup_cache_object(obj); + + /* Cleanup the cache object. Object should be removed from the cache + * now. Increment the refcount before setting cleanup to avoid a race + * condition. A similar pattern is used in remove_url() + */ +#ifdef USE_ATOMICS + apr_atomic_inc(&obj->refcount); +#else + obj->refcount++; +#endif + + obj->cleanup = 1; + +#ifdef USE_ATOMICS + if (!apr_atomic_dec(&obj->refcount)) { + cleanup_cache_object(obj); + } +#else + obj->refcount--; + if (!obj->refcount) { + cleanup_cache_object(obj); + } +#endif } /* * functions return a 'negative' score as lower is better in a priority Q |