If a worker dies while saving a shared dict zone state, the writing
flag remains set in shared memory and survives reloads. Workers
with unsaved changes then receive NGX_AGAIN on every attempt and
keep rearming the save timer, so they never finish graceful shutdown.
Limit how long an exiting worker waits for an outstanding save to
60 seconds since the save started. The shared writing flag is not
cleared and the writer is not interrupted, so a slow save is not
disturbed. Running workers keep waiting as before.
}
if (dict->sh->writing) {
+ rc = NGX_AGAIN;
+
+ if (ngx_exiting
+ && (ngx_msec_int_t) (now - dict->sh->last_write) >= 60000)
+ {
+ /*
+ * The writer may have died during the save, leaving the flag
+ * set. Do not delay the worker exit indefinitely.
+ */
+ rc = NGX_ERROR;
+ }
+
ngx_rwlock_unlock(&dict->sh->rwlock);
ngx_destroy_pool(pool);
- return NGX_AGAIN;
+ return rc;
}
if ((ngx_msec_int_t) (now - dict->sh->last_write) < 1000) {