# HG changeset patch # User Roman Arutyunyan # Date 1559583206 -10800 # Node ID 319242d2ddc9fe77b7d2cca4d0b0bd886029f1f7 # Parent d964b0aee8e715bc6df4112b8b6ff23540c00d79 Upstream: background cache update before cache send (ticket #1782). In case of filter finalization, essential request fields like r->uri, r->args etc could be changed, which affected the cache update subrequest. Also, after filter finalization r->cache could be set to NULL, leading to null pointer dereference in ngx_http_upstream_cache_background_update(). The fix is to create background cache update subrequest before sending the cached response. Since initial introduction in 1aeaae6e9446 (1.11.10) background cache update subrequest was created after sending the cached response because otherwise it blocked the parent request output. In 9552758a786e (1.13.1) background subrequests were introduced to eliminate the delay before sending the final part of the cached response. This also made it possible to create the background cache update subrequest before sending the response. Note that creating the subrequest earlier does not change the fact that in case of filter finalization the background cache update subrequest will likely not have enough time to successfully update the cache entry. Filter finalization leads to the main request termination as soon the current iteration of request processing is complete. diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -597,10 +597,6 @@ ngx_http_upstream_init_request(ngx_http_ u->cache_status = NGX_HTTP_CACHE_MISS; u->request_sent = 1; } - - if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) { - rc = NGX_ERROR; - } } if (rc != NGX_DECLINED) { @@ -902,9 +898,14 @@ ngx_http_upstream_cache(ngx_http_request || c->stale_updating) && !r->background && u->conf->cache_background_update) { - r->cache->background = 1; - u->cache_status = rc; - rc = NGX_OK; + if (ngx_http_upstream_cache_background_update(r, u) == NGX_OK) { + r->cache->background = 1; + u->cache_status = rc; + rc = NGX_OK; + + } else { + rc = NGX_ERROR; + } } break; @@ -1106,10 +1107,6 @@ ngx_http_upstream_cache_background_updat { ngx_http_request_t *sr; - if (!r->cached || !r->cache->background) { - return NGX_OK; - } - if (r == r->main) { r->preserve_body = 1; }