Skip to content

Request reset cannot be observed independently while body polling is paused #352

Description

@spotdemo4

Version

h3 0.0.8, h3-quinn 0.0.10

Platform

Linux desktop 7.1.7 NixOS x86_64 GNU/Linux

Summary

Request reset is invisible while body polling is paused by application backpressure

Code Sample

let (body_tx, mut body_rx) = tokio::sync::mpsc::channel::<Bytes>(1);

// Fill the bounded application queue and stop consuming it.
body_tx.send(Bytes::from_static(b"first")).await?;
let reserve = body_tx.reserve();
tokio::pin!(reserve);

// Client now RESET_STREAMs the request body.
client.reset_request(STREAM_CANCEL_CODE)?;

// The server waits for application capacity and intentionally does not call
// recv.poll_data(). The h3 API has no separate reset event to select here.
assert!(tokio::time::timeout(Duration::from_millis(250), &mut reserve)
    .await
    .is_err());

Once the queue is drained and poll_data() resumes, h3 can return StreamErrorIncoming::StreamTerminated; the delayed visibility is the issue.

Expected Behavior

Request-stream reset should be independently observable even when body delivery is paused, allowing server work and buffered application state for that RPC to be cancelled promptly.

Actual Behavior

A peer RESET_STREAM is surfaced as StreamErrorIncoming::StreamTerminated only when the receive stream is polled. If an application has paused body polling because its bounded downstream channel is full, h3 exposes no independent per-stream reset future to select alongside that application backpressure.

Polling whole-connection closure does not solve this: a stream reset is intentionally local to one stream and does not close the QUIC connection.

Suggested upstream fix

Expose stream reset/closure as an independently pollable event, or define a split receive abstraction where body data and terminal/reset state can be driven without competing for the same mutable polling operation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions