Mercurial > hg > nginx
comparison src/http/ngx_http_upstream.c @ 7514:319242d2ddc9
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.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 03 Jun 2019 20:33:26 +0300 |
parents | c19ca381b2e6 |
children | 08ed570ad93c |
comparison
equal
deleted
inserted
replaced
7513:d964b0aee8e7 | 7514:319242d2ddc9 |
---|---|
595 r->cached = 0; | 595 r->cached = 0; |
596 u->buffer.start = NULL; | 596 u->buffer.start = NULL; |
597 u->cache_status = NGX_HTTP_CACHE_MISS; | 597 u->cache_status = NGX_HTTP_CACHE_MISS; |
598 u->request_sent = 1; | 598 u->request_sent = 1; |
599 } | 599 } |
600 | |
601 if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) { | |
602 rc = NGX_ERROR; | |
603 } | |
604 } | 600 } |
605 | 601 |
606 if (rc != NGX_DECLINED) { | 602 if (rc != NGX_DECLINED) { |
607 ngx_http_finalize_request(r, rc); | 603 ngx_http_finalize_request(r, rc); |
608 return; | 604 return; |
900 | 896 |
901 if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) | 897 if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) |
902 || c->stale_updating) && !r->background | 898 || c->stale_updating) && !r->background |
903 && u->conf->cache_background_update) | 899 && u->conf->cache_background_update) |
904 { | 900 { |
905 r->cache->background = 1; | 901 if (ngx_http_upstream_cache_background_update(r, u) == NGX_OK) { |
906 u->cache_status = rc; | 902 r->cache->background = 1; |
907 rc = NGX_OK; | 903 u->cache_status = rc; |
904 rc = NGX_OK; | |
905 | |
906 } else { | |
907 rc = NGX_ERROR; | |
908 } | |
908 } | 909 } |
909 | 910 |
910 break; | 911 break; |
911 | 912 |
912 case NGX_HTTP_CACHE_UPDATING: | 913 case NGX_HTTP_CACHE_UPDATING: |
1103 static ngx_int_t | 1104 static ngx_int_t |
1104 ngx_http_upstream_cache_background_update(ngx_http_request_t *r, | 1105 ngx_http_upstream_cache_background_update(ngx_http_request_t *r, |
1105 ngx_http_upstream_t *u) | 1106 ngx_http_upstream_t *u) |
1106 { | 1107 { |
1107 ngx_http_request_t *sr; | 1108 ngx_http_request_t *sr; |
1108 | |
1109 if (!r->cached || !r->cache->background) { | |
1110 return NGX_OK; | |
1111 } | |
1112 | 1109 |
1113 if (r == r->main) { | 1110 if (r == r->main) { |
1114 r->preserve_body = 1; | 1111 r->preserve_body = 1; |
1115 } | 1112 } |
1116 | 1113 |