Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#440 closed defect (invalid)

Nginx write content to client instead of 504 when fastcgi timeout expired in configuration

Reported by: Zhe Yang Owned by:
Priority: minor Milestone:
Component: nginx-core Version:
Keywords: Cc:
uname -a: Linux laptop 3.9-1-amd64 #1 SMP Debian 3.9.8-1 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.4.1
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --lock-path=/var/lock/nginx.lock --pid-path=/run/ --with-pcre-jit --with-debug --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_realip_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module --with-http_xslt_module --with-ipv6 --with-mail --with-mail_ssl_module --add-module=/build/nginx-n2G1NA/nginx-1.4.1/debian/modules/nginx-auth-pam --add-module=/build/nginx-n2G1NA/nginx-1.4.1/debian/modules/nginx-dav-ext-module --add-module=/build/nginx-n2G1NA/nginx-1.4.1/debian/modules/nginx-echo --add-module=/build/nginx-n2G1NA/nginx-1.4.1/debian/modules/nginx-upstream-fair --add-module=/build/nginx-n2G1NA/nginx-1.4.1/debian/modules/ngx_http_substitutions_filter_module


I wrote a multi-thread fastcgi application which print http header, then sleep for 5 seconds before writing the actual data. Then I set fastcgi timeout to 4s in nginx.

When nginx's query get timeout, nginx closes the socket, and log timeout to the error log, but it write the http header to client.

Change History (3)

comment:1 by Maxim Dounin, 11 years ago

Resolution: invalid
Status: newclosed

Much like with fastcgi_next_upstream, it's not possible to fix things if part of a response was already sent to a client. Quoting fastcgi_next_upstream docs:

One should bear in mind that passing a request to the next server is only possible if nothing has been sent to a client yet. That is, if an error or timeout occurs in the middle of the transferring of a response, fixing this is impossible.

Best we can do here is to flush buffers to make sure parts of a response we've already got from an upstream server are sent to a client, and make sure a response isn't interpreted by a client as a complete one. This is believed to be what nginx 1.5.3+ does with the following change:

    *) Change: now after receiving an incomplete response from a backend
       server nginx tries to send an available part of the response to a
       client, and then closes client connection.

comment:2 by Zhe Yang, 11 years ago

I agree. In general, this is the only way to fix the problem. But a normal close() won't let the client think the content isn't complete.

With nginx 1.4.1, it's close()d normally. Does 1.5.3+ set SO_LINGER before close()?

Version 0, edited 11 years ago by Zhe Yang (next)

comment:3 by Maxim Dounin, 11 years ago

The HTTP protocol allows to detect if a response isn't complete as long as either Content-Length or Transfer-Encoding: chunked is used. Close with RST isn't a good approach as it might not allow a client to read a response at all.

Note: See TracTickets for help on using tickets.