Upstream: avoid duplicate finalization.

A request may be already finalized when ngx_http_upstream_finalize_request()
is called, due to filter finalization: after filter finalization upstream
can be finalized via ngx_http_upstream_cleanup(), either from
ngx_http_terminate_request(), or because a new request was initiated
to an upstream.  Then the upstream code will see an error returned from
the filter chain and will call the ngx_http_upstream_finalize_request()
function again.

To prevent corruption of various upstream data in this situation, make sure
to do nothing but merely call ngx_http_finalize_request().

Prodded by Yichun Zhang, for details see the thread at
http://nginx.org/pipermail/nginx-devel/2015-February/006539.html.
This commit is contained in:
Maxim Dounin 2015-03-02 21:44:32 +03:00
parent 46a2236f22
commit 2b032e8df6

View File

@ -3751,10 +3751,14 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"finalize http upstream request: %i", rc); "finalize http upstream request: %i", rc);
if (u->cleanup) { if (u->cleanup == NULL) {
/* the request was already finalized */
ngx_http_finalize_request(r, NGX_DONE);
return;
}
*u->cleanup = NULL; *u->cleanup = NULL;
u->cleanup = NULL; u->cleanup = NULL;
}
if (u->resolved && u->resolved->ctx) { if (u->resolved && u->resolved->ctx) {
ngx_resolve_name_done(u->resolved->ctx); ngx_resolve_name_done(u->resolved->ctx);