]> granicus.if.org Git - apache/commitdiff
Fix segfault in mod_mem_cache when caching streaming dynamic content.
authorBill Stoddard <stoddard@apache.org>
Thu, 18 Dec 2003 21:22:41 +0000 (21:22 +0000)
committerBill Stoddard <stoddard@apache.org>
Thu, 18 Dec 2003 21:22:41 +0000 (21:22 +0000)
PR: 21285, 21287

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102086 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/experimental/mod_mem_cache.c

diff --git a/CHANGES b/CHANGES
index ca37fafeae80f797206182333d049c2646e9ba2a..282e304f7d11fdae735e9172fa55974c68f7ee12 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
 Changes with Apache 2.1.0-dev
 
   [Remove entries to the current 2.0 section below, when backported]
+  *) Fix segfault in mod_mem_cache cache_insert() due to cache size
+     becoming negative.  PR: 21285, 21287
+     [Bill Stoddard, Massimo Torquati, Jean-Jacques Clar]
 
   *) Add Polish translation of error messages.  PR 25101.
      [Tomasz Kepczynski <tomek jot23.org>]
index 8f93872252401aba45e01ae1001f05241abe24ea..7818825be3b77043a601eabee5b7adfdbe7f451b 100644 (file)
@@ -1043,7 +1043,28 @@ static apr_status_t write_body(cache_handle_t *h, request_rec *r, apr_bucket_bri
                 if (sconf->lock) {
                     apr_thread_mutex_lock(sconf->lock);
                 }
-                cache_remove(sconf->cache_cache, obj);
+                if (obj->cleanup) {
+                    /* If obj->cleanup is set, the object has been prematurly 
+                     * ejected from the cache by the garbage collector. Add the
+                     * object back to the cache. If an object with the same key is 
+                     * found in the cache, eject it in favor of the completed obj.
+                     */
+                    cache_object_t *tmp_obj =
+                      (cache_object_t *) cache_find(sconf->cache_cache, obj->key);
+                    if (tmp_obj) {
+                        cache_remove(sconf->cache_cache, tmp_obj);
+                        sconf->object_cnt--;
+                        sconf->cache_size -= mobj->m_len;
+                        tmp_obj->cleanup = 1;
+                        if (!tmp_obj->refcount) {
+                            cleanup_cache_object(tmp_obj);
+                        }
+                    }
+                    obj->cleanup = 0;
+                }
+                else {
+                    cache_remove(sconf->cache_cache, obj);
+                }
                 mobj->m_len = obj->count;
                 cache_insert(sconf->cache_cache, obj);                
                 sconf->cache_size -= (mobj->m_len - obj->count);