[nginx] Cache: ignore long locked entries during forced expire.
Dmitry Volyntsev
xeioex at nginx.com
Thu May 18 15:41:44 UTC 2017
details: http://hg.nginx.org/nginx/rev/ab199f0eb8e8
branches:
changeset: 7002:ab199f0eb8e8
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu May 18 18:39:16 2017 +0300
description:
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:
src/http/ngx_http_file_cache.c | 57 ++++++++++++++++++++++++++++++++---------
1 files changed, 44 insertions(+), 13 deletions(-)
diffs (91 lines):
diff -r 08537eab4f23 -r ab199f0eb8e8 src/http/ngx_http_file_cache.c
--- a/src/http/ngx_http_file_cache.c Thu May 18 14:17:00 2017 +0300
+++ b/src/http/ngx_http_file_cache.c Thu May 18 18:39:16 2017 +0300
@@ -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_ht
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_ht
if (fcn->count == 0) {
ngx_http_file_cache_delete(cache, q, name);
wait = 0;
-
- } else {
- if (--tries) {
- continue;
- }
-
- wait = 1;
+ break;
}
+ 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);
+
+ /*
+ * 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;
}
More information about the nginx-devel
mailing list