diff options
author | Dmitry Volyntsev <xeioex@nginx.com> | 2017-05-18 18:39:16 +0300 |
---|---|---|
committer | Dmitry Volyntsev <xeioex@nginx.com> | 2017-05-18 18:39:16 +0300 |
commit | c6df6bf9239a54655525b7871a66dd35744692c2 (patch) | |
tree | 6f4dcf20783d0dbe489b3626489ba0b957d36e75 /src/http/ngx_http_file_cache.c | |
parent | 9359155b2fb443ac3c2cf0d897d5db668585235b (diff) | |
download | nginx-c6df6bf9239a54655525b7871a66dd35744692c2.tar.gz nginx-c6df6bf9239a54655525b7871a66dd35744692c2.zip |
Cache: ignore long locked entries during forced expire.
Abnormally exited workers may leave locked cache entries, this can
result in the cache size on disk exceeding max_size and shared memory
exhaustion.
This change mitigates the issue by ignoring locked entries during forced
expire. It also increases the visibility of the problem by logging such
entries.
Diffstat (limited to 'src/http/ngx_http_file_cache.c')
-rw-r--r-- | src/http/ngx_http_file_cache.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index b635b354e..a823c51ae 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -1700,13 +1700,14 @@ ngx_http_file_cache_cleanup(void *data) static time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) { - u_char *name; + u_char *name, *p; size_t len; time_t wait; ngx_uint_t tries; ngx_path_t *path; - ngx_queue_t *q; + ngx_queue_t *q, *sentinel; ngx_http_file_cache_node_t *fcn; + u_char key[2 * NGX_HTTP_CACHE_KEY_LEN]; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache forced expire"); @@ -1723,13 +1724,21 @@ ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) wait = 10; tries = 20; + sentinel = NULL; ngx_shmtx_lock(&cache->shpool->mutex); - for (q = ngx_queue_last(&cache->sh->queue); - q != ngx_queue_sentinel(&cache->sh->queue); - q = ngx_queue_prev(q)) - { + for ( ;; ) { + if (ngx_queue_empty(&cache->sh->queue)) { + break; + } + + q = ngx_queue_last(&cache->sh->queue); + + if (q == sentinel) { + break; + } + fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, @@ -1740,15 +1749,37 @@ ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) if (fcn->count == 0) { ngx_http_file_cache_delete(cache, q, name); wait = 0; + break; + } - } else { - if (--tries) { - 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); + (void) ngx_hex_dump(p, fcn->key, len); - wait = 1; + /* + * abnormally exited workers may leave locked cache entries, + * and although it may be safe to remove them completely, + * we prefer to just move them to the top of the inactive queue + */ + + ngx_queue_remove(q); + fcn->expire = ngx_time() + cache->inactive; + ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); + + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "ignore long locked inactive cache entry %*s, count:%d", + (size_t) 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); + + if (sentinel == NULL) { + sentinel = q; } + if (--tries) { + continue; + } + + wait = 1; break; } |