summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorBill Stoddard <stoddard@apache.org>2002-06-15 16:49:19 +0000
committerBill Stoddard <stoddard@apache.org>2002-06-15 16:49:19 +0000
commitfabbd581969751e3030b7bf40afc3aef6d122e9b (patch)
tree64bae1ba7ac487ab0f8d28eeee336b1a8cd850c3 /modules
parente397f79a00d14c7fdace497538a9c295e08fa332 (diff)
downloadhttpd-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.c29
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