]> git.kaiwu.me - nginx.git/commit
HTTP/2: fixed sendfile() aio handling.
authorMaxim Dounin <mdounin@mdounin.ru>
Thu, 25 Nov 2021 19:02:10 +0000 (22:02 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Thu, 25 Nov 2021 19:02:10 +0000 (22:02 +0300)
commit83e92a2edd6bf7c6867b653284ac44962c4e33c9
tree55673052e76b4d5f7002d61ae9b94db0e0f6fa41
parent2361e98a34ca3b66c45fbb4e906401b430e41013
HTTP/2: fixed sendfile() aio handling.

With sendfile() in threads ("aio threads; sendfile on;"), client connection
can block on writing, waiting for sendfile() to complete.  In HTTP/2 this
might result in the request hang, since an attempt to continue processing
in thread event handler will call request's write event handler, which
is usually stopped by ngx_http_v2_send_chain(): it does nothing if there
are no additional data and stream->queued is set.  Further, HTTP/2 resets
stream's c->write->ready to 0 if writing blocks, so just fixing
ngx_http_v2_send_chain() is not enough.

Can be reproduced with test suite on Linux with:

TEST_NGINX_GLOBALS_HTTP="aio threads; sendfile on;" prove h2*.t

The following tests currently fail: h2_keepalive.t, h2_priority.t,
h2_proxy_max_temp_file_size.t, h2.t, h2_trailers.t.

Similarly, sendfile() with AIO preloading on FreeBSD can block as well,
with similar results.  This is, however, harder to reproduce, especially
on modern FreeBSD systems, since sendfile() usually does not return EBUSY.

Fix is to modify ngx_http_v2_send_chain() so it actually tries to send
data to the main connection when called, and to make sure that
c->write->ready is set by the relevant event handlers.
src/http/ngx_http_copy_filter_module.c
src/http/ngx_http_upstream.c
src/http/v2/ngx_http_v2_filter_module.c