False `SendRequest` readiness for HTTP/1 connections
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 55/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- rust
- Ambito
- backend-api-design, networking
Direzione di ricerca
Start with the reproduction in the issue and compare the readiness behavior against hyper versions before and after 1.12. Then trace how http1::SendRequest readiness interacts with the connection dispatch queue, using #4207 and #4208 for context. Done when readiness stays pending while a request is in flight and the reproduction no longer observes immediate cancellation.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Version
hyper 1.12
Platform
Darwin 25.6.0
Summary
I believe to have found a readiness race in hyper 1.12 (and at the time of writing master), possibly as a result of the fix for #4207.
http1::SendRequest can signal readiness while a request is still in flight. Using it to send a request results in the request being cancelled immediately.
I have tried to conjure a minimal reproduction example in this gist. With it, you can also set the hyper dependency to <1.12 and observe that the repro test no longer detects the issue.
Code Sample
use std::future::Future;
use std::future::poll_fn;
use std::io;
use std::pin::Pin;
use std::pin::pin;
use std::task::Context;
use std::task::Poll;
use hyper::Request;
use hyper::client::conn::http1;
use hyper::rt::Read;
use hyper::rt::ReadBufCursor;
use hyper::rt::Write;
// Accept writes, but never respond or close: the first request stays in flight.
struct SilentPeer;
impl Read for SilentPeer {
fn poll_read(
self: Pin<&mut Self>,
_: &mut Context<'_>,
_: ReadBufCursor<'_>,
) -> Poll<io::Result<()>> {
Poll::Pending
}
}
impl Write for SilentPeer {
fn poll_write(
self: Pin<&mut Self>,
_: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
Poll::Ready(Ok(buf.len()))
}
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
}
#[tokio::test]
async fn successful_readiness_must_not_be_withdrawn_before_send() {
let (mut sender, connection) = http1::handshake::<_, String>(SilentPeer).await.unwrap();
let mut connection = pin!(connection);
poll_fn(|cx| {
assert!(connection.as_mut().poll(cx).is_pending());
Poll::Ready(())
})
.await;
sender.ready().await.unwrap();
// Retain this future: dropping it would cancel the request.
let _first = sender.send_request(Request::new(String::new()));
poll_fn(|cx| {
// Force the dispatch queue to report Pending despite the queued request.
while let Poll::Ready(budget) = tokio::task::coop::poll_proceed(cx) {
budget.made_progress();
}
assert!(connection.as_mut().poll(cx).is_pending());
match sender.poll_ready(cx) {
Poll::Pending => return Poll::Ready(()), // No false readiness: correct.
Poll::Ready(result) => result.unwrap(), // False readiness!
}
// Model the connection task running on another worker before our send.
let mut driver = pin!(tokio::task::unconstrained(connection.as_mut()));
assert!(driver.as_mut().poll(cx).is_pending());
assert!(
!sender.is_closed(),
"the peer has not closed the connection"
);
let mut second = pin!(sender.send_request(Request::new(String::new())));
let result = second.as_mut().poll(cx);
assert!(
!matches!(result, Poll::Ready(Err(_))),
"send_request failed after poll_ready returned Ready(Ok(())): {result:?}"
);
Poll::Ready(())
})
.await;
}
Expected Behavior
The http1::SendRequest indicates Poll::Pending until it is ready.
Actual Behavior
The http1::SendRequest indicates Poll::Ready and the http1::SendRequest::send_request future fails immediately with an error indicating request cancellation.
Additional Context
Possibly related issues:
- #4207
Possibly related pull requests:
- #4208
- Lingua principale
- Rust
- Stelle
- 16.4k
- Fork
- 1.8k
- Merge medio
- 1g 13h
- PR unite (30g)
- 12
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di hyperium/hyper
-
C-feature
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 65/100
hyperium/hyper#2652 · 4 reazioni ·
I maintainer di solito rispondono entro 1 giorno
-
C-feature
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 1 giorno
-
can't upgrade request that came in with `Connection: close, Upgrade`Forse già presa @akasakariko l’ha presa 3 giorni fa. ApertaC-bug
Difficoltà 3/5 1-2 giorni Idoneità per principianti 62/100
hyperium/hyper#4244 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di hyperium/hyper
Issue simili
-
bug priority: low ui
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
storytold/photocraft#10370 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
area:doc bug in progress needs-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
bherbruck/solvecraft#9634 · 2 commenti · 1 reazione ·
-
inflate: total_in uses plain += on c_ulong (32-bit on Windows), panics in debug for streams > 4 GiBAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
trifectatechfoundation/zlib-rs#570 · 1 commento ·
-
bug discord-triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
LanternOps/breeze#10755 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
aranya-project/aranya#803 ·