Segfault when interpreting cached X-Accel-Redirect response

Jan Prachař jan.prachar at gmail.com
Fri Feb 2 12:47:51 UTC 2024


On Fri, 2024-02-02 at 12:48 +0100, Jiří Setnička via nginx-devel wrote:
> Hello,
> 
> Also, I believe that the core of the problem is because of the 
> ngx_http_finalize_request(r, NGX_DONE); call in the 
> ngx_http_upstream_process_headers function. This call is needed when 
> doing an internal redirect after the real upstream request (to close the 
> upstream request), but when serving from the cache, there is no upstream 
> request to close and this call causes ngx_http_set_lingering_close to be 
> called from the ngx_http_finalize_connection with no active request on 
> the connection yielding to the segfault.

Hello,

I am Jiří's colleague, and so I have taken a closer look at the problem. Another
indication of the issue is the alert in the error log for non-keepalive connections,
stating "http request count is zero while closing request."

Upon reviewing the nginx source code, I discovered that the function
ngx_http_upstream_finalize_request(), when called with rc = NGX_DECLINED, does not invoke
ngx_http_finalize_request(). However, when there is nothing to clean up (u->cleanup ==
NULL), it does. Therefore, I believe the appropriate fix is to follow the patch below.

Best, Jan Prachař

# User Jan Prachař <jan.prachar at gmail.com>
# Date 1706877176 -3600
#      Fri Feb 02 13:32:56 2024 +0100
# Node ID 851c994b48c48c9cd3d32b9aa402f4821aeb8bb2
# Parent  cf3d537ec6706f8713a757df256f2cfccb8f9b01
Upstream: Fix "request count is zero" when procesing X-Accel-Redirect

ngx_http_upstream_finalize_request(r, u, NGX_DECLINED) should not call
ngx_http_finalize_request().

diff -r cf3d537ec670 -r 851c994b48c4 src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c      Thu Nov 26 21:00:25 2020 +0100
+++ b/src/http/ngx_http_upstream.c      Fri Feb 02 13:32:56 2024 +0100
@@ -4340,6 +4340,11 @@
 
     if (u->cleanup == NULL) {
         /* the request was already finalized */
+
+        if (rc == NGX_DECLINED) {
+            return;
+        }
+
         ngx_http_finalize_request(r, NGX_DONE);
         return;
     }


More information about the nginx-devel mailing list