CONCEPT Cited by 1 source
AsyncRead contract¶
Definition¶
AsyncRead (and its sibling AsyncWrite) are async Rust
traits that extend Future to
streaming I/O. Where a one-shot Future resolves once and then
can't be polled again, an AsyncRead's poll_read method
returns Poll::Ready(Ok(n)) every time there's data ready to
read. The contract is: keep calling poll_read in a loop until
it stops being Ready (i.e. returns Pending).
From Fly.io's 2025-02 proxy post:
"With network programming, data usually arrives in streams, which you want to track and make progress on as you can. So async Rust provides AsyncRead and AsyncWrite traits, which build on Futures, and provide methods like poll_read that return Ready every time there's data ready."
Implicit contract that can't be checked¶
The crucial and easy-to-miss half of the contract is: every
Ready must make forward progress in the underlying state
machine. If poll_read returns Ready without advancing —
e.g. without actually consuming buffered bytes, without
transitioning a TLS-protocol state, without advancing the read
cursor — the caller (who is faithfully looping until Pending)
spins on it forever.
Fly.io: "Since the idea of AsyncRead is that you keep
poll_reading until it stops being Ready, this too is an
infinite loop."
This is a contract that is easy to write, impossible for the
compiler to check, and catastrophic to violate — all the
ingredients for exactly the kind of subtle
busy-loop that the 2025-02
rustls TlsStream bug instantiated.
Seen in¶
- sources/2025-02-26-flyio-taming-a-voracious-rust-proxy —
canonical wiki instance. On TLS orderly shutdown
(
close_notifyAlert) with bytes still buffered in the underlying socket,tokio_rustls::server::TlsStreamreturnedReadyfrompoll_readin a state its own machine couldn't progress from — caller loop → 100% CPU. The failure was the exact second-footgun Fly.io's async-Rust primer warned about.
Related¶
- concepts/async-rust-future — the primitive AsyncRead extends.
- concepts/rust-waker — the wake-up handle underneath.
- concepts/spurious-wakeup-busy-loop — the pathology that
manifests when
Readylies about progress. - systems/tokio / systems/rustls / systems/tokio-rustls — the Rust async / TLS stack where this contract matters.
- companies/flyio