]> git.kaiwu.me - njs.git/commitdiff
Modules: fixed shared dict state save stuck forever
authorvitalyn <jc@vitalyn.com>
Fri, 2 Oct 2026 21:50:43 +0000 (23:50 +0200)
committerDmitry Volyntsev <xeioexception@gmail.com>
Thu, 15 Oct 2026 01:49:05 +0000 (18:49 -0700)
The "dirty" and "writing" flags of a shared dict were bit fields of
the same word.  ngx_js_dict_save() clears "writing" without holding
the lock, while set(), incr(), delete() and clear() set "dirty" under
the write lock in other workers.  The two read-modify-write operations
could interleave and leave "writing" set for good.

After that, every save attempt returned NGX_AGAIN: the state file was
never written again, and the save timer, re-armed every second and not
cancelable, prevented any worker of the zone from finishing a graceful
shutdown, regardless of worker_shutdown_timeout.  The flag lives in
shared memory, so it survived reloads.

The fix is to store the flags in separate words.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This fixes #1136.

nginx/ngx_js_shared_dict.c

index 2631f7e713f1e9f57b3339044dfce67afa7bbb8e..30de86bf86d9a52128319ee9643f3f81d15a05e2 100644 (file)
@@ -19,8 +19,8 @@ typedef struct {
     ngx_rbtree_t           rbtree_expire;
     ngx_rbtree_node_t      sentinel_expire;
 
-    unsigned               dirty:1;
-    unsigned               writing:1;
+    ngx_uint_t             dirty;
+    ngx_uint_t             writing;
 } ngx_js_dict_sh_t;