]> git.kaiwu.me - nginx.git/commitdiff
Upstream: avoid duplicate finalization.
authorMaxim Dounin <mdounin@mdounin.ru>
Mon, 2 Mar 2015 18:44:32 +0000 (21:44 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Mon, 2 Mar 2015 18:44:32 +0000 (21:44 +0300)
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.

src/http/ngx_http_upstream.c

index 23208c80ee85856963d601e2c8e20af196da408a..7066d14afa533452c21022cf3ac0c51a7f3544e8 100644 (file)
@@ -3751,11 +3751,15 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "finalize http upstream request: %i", rc);
 
-    if (u->cleanup) {
-        *u->cleanup = NULL;
-        u->cleanup = NULL;
+    if (u->cleanup == NULL) {
+        /* the request was already finalized */
+        ngx_http_finalize_request(r, NGX_DONE);
+        return;
     }
 
+    *u->cleanup = NULL;
+    u->cleanup = NULL;
+
     if (u->resolved && u->resolved->ctx) {
         ngx_resolve_name_done(u->resolved->ctx);
         u->resolved->ctx = NULL;