Skip to content

Fix write to check poll_ready before sending data - #6

Draft
0x676e67 wants to merge 25 commits into
mainfrom
poll_ready
Draft

Fix write to check poll_ready before sending data#6
0x676e67 wants to merge 25 commits into
mainfrom
poll_ready

Conversation

@0x676e67

Copy link
Copy Markdown
Owner

No description provided.

@0x676e67
0x676e67 marked this pull request as draft June 10, 2026 11:16
@0x676e67
0x676e67 changed the base branch from main to qpack-decoder June 10, 2026 11:16

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for QPACK dynamic tables in the HTTP/3 implementation, including state synchronization, encoder/decoder stream handling, and blocked stream management. It also transitions the QUIC stream sending API from a synchronous send_data to an asynchronous poll_send_data model across h3, h3-quinn, and h3-webtransport. Feedback on these changes highlights a critical issue in h3/src/connection.rs where calling self.waker().wake() unconditionally inside poll_qpack_encoder can trigger an infinite busy-loop and 100% CPU usage when a partial QPACK instruction is received; the waker should instead only be signaled when progress is actually made.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

I am having trouble creating individual review comments. Click here to see my feedback.

h3/src/connection.rs (599-611)

critical

Calling self.waker().wake() unconditionally on every iteration of the loop in poll_qpack_encoder can cause an infinite busy-loop (100% CPU usage) when a partial QPACK instruction is received.

Specifically, if encoder_recv contains some bytes but not enough to form a complete instruction, decoder.on_encoder_recv will consume 0 bytes and return Ok. Since encoder_recv.buf().remaining() == before is true, the loop will break and return Poll::Pending. However, because self.waker().wake() was already called, the executor will immediately poll the connection task again, repeating the same process and busy-looping until more data arrives to complete the instruction.

We should only call self.waker().wake() if we actually made progress (i.e., after checking that encoder_recv.buf().remaining() != before).

                if let Err(err) = decode_result {
                    return Poll::Ready(Err(self.handle_connection_error(
                        InternalConnectionError::new(
                            Code::QPACK_ENCODER_STREAM_ERROR,
                            format!("invalid QPACK encoder stream instruction: {}", err),
                        ),
                    )));
                }

                if encoder_recv.buf().remaining() == before {
                    break;
                }

                self.waker().wake();

Base automatically changed from qpack-decoder to main June 22, 2026 09:08
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