Skip to content

Conversation

@lthiery
Copy link
Contributor

@lthiery lthiery commented Dec 2, 2025

This is a follow up on #3952 which was reverted by #3977 after reports in #3976.

The conceptual problem this is trying to fix is that the dispatch loop may poll the Write side and determine readiness (either rt::Write::poll_write or rt::Write::poll_flush are ready), but will return Poll::Pending to the executor and stall; if neither write nor flush are pending, then nothing will wake us.

The initial fix did not treat the common "unbuffered" implementation where poll_flush always returns Poll::Ready; I question the correctness of such a response, as my understanding of flush would be that the "the bytes are flushed out and we may write again", but I can't argue with what the current convention is.

For testing, in addition to the contrived hyper Stream that triggers the stall from the previous PR (ie: ReadyOnPollStream), I've also added an UnbufferedStream to simulate the implementation where flush always returns Poll::Ready. The test fails as expected with #3952.

The additional fix in this PR is to check again if the connection is writable if and only if we are proceeding to loop because we think the connection may be writable (ie: write or flush have returned Ready). If the write is indeed still pending, we can safely return from the loop without scheduling a waker because we know the writer's waker will schedule us to proceed with the write half. This additional check resolves the hot looping issue for unbuffered streams in #3952.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant