Skip to content

Conversation

asonix
Copy link
Contributor

@asonix asonix commented Aug 7, 2025

An alternate solution to #3715

The existing pipelining behavior of the h1 dispatcher can cause client timeouts if the entire request body isn't read. It puts the dispatcher into a state where it refuses to read more (payload dropped) but there are still bytes in the buffer from the request body.

This solution adds the SHUTDOWN flag in addition to the FINISHED flag when completing a response when both the following are true:

  1. There are no messages in this.messages
  2. There is still a payload in this.payload

This combination implies two things. First, that we have not parsed a pipelined request after the request we have just responded to. Second, that the current request payload has not been fed an EOF. Because there are no pipelined requests, we know that the current request payload belongs to the request we have just responded to, and because the request payload has not been fed an EOF, we know we never finished reading it.

When this occurs, adding the SHUTDOWN flag to the dispatcher triggers a flush and a poll_shutdown on the IO resource on the next poll.

PR Type

Bug Fix

PR Checklist

  • Tests for the changes have been added / updated.
  • Documentation comments have been added / updated.
  • A changelog entry has been made for the appropriate packages.
  • Format code with the latest stable rustfmt.
  • (Team) Label with affected crates and semver status.

Overview

The existing pipelining behavior of the h1 dispatcher can cause client timeouts
if the entire request body isn't read. It puts the dispatcher into a state where
it refuses to read more (payload dropped) but there are still bytes in the buffer
from the request body.

This solution adds the SHUTDOWN flag in addition to the FINISHED flag
when completing a response when both the following are true:

1. There are no messages in `this.messages`
2. There is still a payload in `this.payload`

This combination implies two things. First, that we have not parsed a
pipelined request after the request we have just responded to. Second,
that the current request payload has not been fed an EOF. Because there
are no pipelined requests, we know that the current request payload
belongs to the request we have just responded to, and because the
request payload has not been fed an EOF, we know we never finished
reading it.

When this occurs, adding the SHUTDOWN flag to the dispatcher triggers a
`flush` and a `poll_shutdown` on the IO resource on the next poll.
@robjtede robjtede added A-http project: actix-http B-semver-patch labels Aug 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-http project: actix-http B-semver-patch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Client Connection timeouts when running behind loadbalancers
2 participants