]> git.kaiwu.me - nginx.git/commitdiff
fix race condition if during reconfiguration two cache managers try
authorIgor Sysoev <igor@sysoev.ru>
Thu, 2 Sep 2010 14:31:47 +0000 (14:31 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Thu, 2 Sep 2010 14:31:47 +0000 (14:31 +0000)
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

src/http/ngx_http_cache.h
src/http/ngx_http_file_cache.c

index 1a23e4620063564c6142e4de1a57fd56848c9dd0..b511a0b9121eb3a3616fa585b469efe2df40c2f8 100644 (file)
@@ -43,7 +43,8 @@ typedef struct {
     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;
index d14a7c5e6b39435a50d4f4a92c3931d785486414..0d97e94ecb82af831609d75006e4249b7cfb0c68 100644 (file)
@@ -582,6 +582,7 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
     fcn->uses = 1;
     fcn->count = 1;
     fcn->updating = 0;
+    fcn->deleting = 0;
 
 renew:
 
@@ -1102,6 +1103,10 @@ ngx_http_file_cache_expire(ngx_http_file_cache_t *cache)
             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 @@ ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q,
         *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_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q,
 
         ngx_shmtx_lock(&cache->shpool->mutex);
         fcn->count--;
+        fcn->deleting = 0;
     }
 
     if (fcn->count == 0) {
@@ -1431,6 +1438,7 @@ ngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c)
         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;