Skip to content

epoll shutdown: a request in progress is not answered on a loop with no HTTP/2 conn (cut with no response) #1166

Open

Description

@FumingPower3925

Found by the review of #1163. Not a regression against v1.5.11 (it behaved the same), but part of the shutdown contract the v1.6.0 gates (#885, #884) are meant to give.

What happens

On epoll, the gate's "answer the request in progress" (read the unread request and answer it with close-after, #1138) only exists on loops that hold an HTTP/2 conn. A server whose clients are all HTTP/1 never raises the gate: a request in progress at Shutdown (slow upload, headers in pieces, a body arriving, a request still unread in the kernel) is never read. It waits behind any drain on its loop and is then cut by the last phase (RST with unread bytes) with no answer. std answers it; io_uring answers it during its send drain when the worker has sends pending (else cuts it too).

Measured (review of #1163, lowered HTTP/2 conn count so one loop has none)

"the response to the upload: i/o timeout: a request in progress was not answered" in 3 of 24 arm runs, "write: broken pipe: a request in progress was cut" in 1 of 24; for a request still unread in the kernel: no answer, FIN at 0.

Fix direction

Run the gate's read-and-answer pass on every epoll loop at Shutdown, not only on loops with an HTTP/2 conn (the same pass closeIdleH1's counterpart runs for a pool-wait loop), and give io_uring the same pass when its worker has no sends pending. Test on every engine (epoll, io_uring, adaptive, std) with an HTTP/1-only server: a slow upload in progress at Shutdown gets its response with Connection: close.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions