aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2010-09-02 14:31:47 +0000
committerIgor Sysoev <igor@sysoev.ru>2010-09-02 14:31:47 +0000
commita256afd0649210dd04772d1b9d3a5e8c275e67ca (patch)
tree29cface5b43065b8f4096e945e4c413cca653f83
parent3730543c26e5634be792813c312e86dcf77fc3a0 (diff)
downloadnginx-a256afd0649210dd04772d1b9d3a5e8c275e67ca.tar.gz
nginx-a256afd0649210dd04772d1b9d3a5e8c275e67ca.zip
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
-rw-r--r--src/http/ngx_http_cache.h3
-rw-r--r--src/http/ngx_http_file_cache.c8
2 files changed, 10 insertions, 1 deletions
diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h
index 1a23e4620..b511a0b91 100644
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -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;
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index d14a7c5e6..0d97e94ec 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -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;