changeset 3755:76e3a93821b1

fix race condition if during reconfiguration two cache managers try to delete old inactive entries: one of them removes a entry just locked by other manager from the queue and the rbtree as long inactive entry, causes the latter manager to segfault leaving cache mutex locked, the bug has been introduced in r3727
author Igor Sysoev <igor@sysoev.ru>
date Thu, 02 Sep 2010 14:31:47 +0000
parents 5f58badd13ed
children 7224d008faaf
files src/http/ngx_http_cache.h src/http/ngx_http_file_cache.c
diffstat 2 files changed, 10 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_cache.h	Thu Sep 02 14:02:57 2010 +0000
+++ b/src/http/ngx_http_cache.h	Thu Sep 02 14:31:47 2010 +0000
@@ -43,7 +43,8 @@
     unsigned                         error:10;
     unsigned                         exists:1;
     unsigned                         updating:1;
-                                     /* 12 unused bits */
+    unsigned                         deleting:1;
+                                     /* 11 unused bits */
 
     ngx_file_uniq_t                  uniq;
     time_t                           expire;
--- a/src/http/ngx_http_file_cache.c	Thu Sep 02 14:02:57 2010 +0000
+++ b/src/http/ngx_http_file_cache.c	Thu Sep 02 14:31:47 2010 +0000
@@ -582,6 +582,7 @@
     fcn->uses = 1;
     fcn->count = 1;
     fcn->updating = 0;
+    fcn->deleting = 0;
 
 renew:
 
@@ -1102,6 +1103,10 @@
             continue;
         }
 
+        if (fcn->deleting) {
+            continue;
+        }
+
         p = ngx_hex_dump(key, (u_char *) &fcn->node.key,
                          sizeof(ngx_rbtree_key_t));
         len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t);
@@ -1153,6 +1158,7 @@
         *p = '\0';
 
         fcn->count++;
+        fcn->deleting = 1;
         ngx_shmtx_unlock(&cache->shpool->mutex);
 
         len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN;
@@ -1168,6 +1174,7 @@
 
         ngx_shmtx_lock(&cache->shpool->mutex);
         fcn->count--;
+        fcn->deleting = 0;
     }
 
     if (fcn->count == 0) {
@@ -1431,6 +1438,7 @@
         fcn->error = 0;
         fcn->exists = 1;
         fcn->updating = 0;
+        fcn->deleting = 0;
         fcn->uniq = c->uniq;
         fcn->valid_sec = c->valid_sec;
         fcn->body_start = c->body_start;