[PATCH] Do not break downstream connection on proxy_cache write error
Kipras Mancevicius
kiprasm at gmail.com
Mon May 2 13:36:09 UTC 2022
# HG changeset patch
# User Kipras Mancevicius <kiprasm at gmail.com>
# Date 1651495240 -10800
# Mon May 02 15:40:40 2022 +0300
# Branch proxy_cache_write_disk_full_fix
# Node ID e6e708fd7958987027f6de7748d948e5015ed32b
# Parent a736a7a613ea6e182ff86fbadcb98bb0f8891c0b
Do not break downstream connection on proxy_cache write error
Continue sending response to downstream connection and delete temp cache file on
upstream connection finalization.
diff -r a736a7a613ea -r e6e708fd7958 src/core/ngx_file.c
--- a/src/core/ngx_file.c Tue Feb 08 17:35:27 2022 +0300
+++ b/src/core/ngx_file.c Mon May 02 15:40:40 2022 +0300
@@ -765,6 +765,13 @@
ngx_delete_file_n " \"%s\" failed", name);
}
+ } else {
+ /*
+ * if the file failed to fully copy (e.g. target disk is full) - it
+ * may remain (partially written) in the target disk. Attempt to
+ * delete it.
+ */
+ ngx_delete_file(name);
}
ngx_free(name);
diff -r a736a7a613ea -r e6e708fd7958 src/event/ngx_event_pipe.c
--- a/src/event/ngx_event_pipe.c Tue Feb 08 17:35:27 2022 +0300
+++ b/src/event/ngx_event_pipe.c Mon May 02 15:40:40 2022 +0300
@@ -753,10 +753,21 @@
out = p->writing;
p->writing = NULL;
- n = ngx_write_chain_to_temp_file(p->temp_file, NULL);
+ /*
+ * stop writing to cache on cache write fail, but keep sending response
+ * downstream. Incomplete temp cache file will be deleted later.
+ */
+ if (p->cache_write_fail) {
+ return NGX_BUSY;
+ } else {
+ n = ngx_write_chain_to_temp_file(p->temp_file, NULL);
- if (n == NGX_ERROR) {
- return NGX_ABORT;
+ if (n == NGX_ERROR) {
+ p->cache_write_fail = 1;
+ p->cacheable = 0;
+
+ return NGX_BUSY;
+ }
}
goto done;
@@ -777,6 +788,23 @@
out = p->in;
}
+ /*
+ * stop writing to cache on cache write fail, but keep sending response
+ * downstream. Incomplete temp cache file will be deleted later.
+ */
+ if (p->cache_write_fail) {
+ return NGX_BUSY;
+ } else {
+ n = ngx_write_chain_to_temp_file(p->temp_file, out);
+
+ if (n == NGX_ERROR) {
+ p->cache_write_fail = 1;
+ p->cacheable = 0;
+
+ return NGX_BUSY;
+ }
+ }
+
if (!p->cacheable) {
size = 0;
diff -r a736a7a613ea -r e6e708fd7958 src/event/ngx_event_pipe.h
--- a/src/event/ngx_event_pipe.h Tue Feb 08 17:35:27 2022 +0300
+++ b/src/event/ngx_event_pipe.h Mon May 02 15:40:40 2022 +0300
@@ -66,6 +66,7 @@
unsigned downstream_error:1;
unsigned cyclic_temp_file:1;
unsigned aio:1;
+ unsigned cache_write_fail:1;
ngx_int_t allocated;
ngx_bufs_t bufs;
diff -r a736a7a613ea -r e6e708fd7958 src/http/ngx_http_file_cache.c
--- a/src/http/ngx_http_file_cache.c Tue Feb 08 17:35:27 2022 +0300
+++ b/src/http/ngx_http_file_cache.c Mon May 02 15:40:40 2022 +0300
@@ -1377,6 +1377,16 @@
cache = c->file_cache;
+ if (r->upstream && r->upstream->pipe && r->upstream->pipe->cache_write_fail) {
+ /*
+ * if cache file failed to be written (e.g. cache disk is full) - we
+ * kept sending response downstream and then delete the incomplete temp
+ * cache file here (after response is served downstream).
+ */
+ ngx_http_file_cache_free(cache, tf);
+ return;
+ }
+
c->updated = 1;
c->updating = 0;
More information about the nginx-devel
mailing list