rust-lang / futures-rs

Zero-cost asynchronous programming in Rust
https://rust-lang.github.io/futures-rs/
Apache License 2.0
5.38k stars 622 forks source link

Streams: `wake` may not poll futures if two streams are combined (and only one future is polled) #2775

Open DragonDev1906 opened 1 year ago

DragonDev1906 commented 1 year ago

Unless I'm mistaken, the combinators listed below (and likely others, too), which all combine two features, break the contract of futures::task::Waker. Is this a problem?

As long as the executor keeps running and the task is not finished, it is guaranteed that each invocation of wake() (or wake_by_ref()) will be followed by at least one poll() of the task to which this Waker belongs. This makes it possible to temporarily yield to other tasks while running potentially unbounded processing loops.

Note that the above implies that multiple wake-ups may be coalesced into a single poll() invocation by the runtime.

Also note that yielding to competing tasks is not guaranteed: it is the executor’s choice which task to run and the executor may choose to run the current task again.

Source: https://docs.rs/futures/latest/futures/task/struct.Waker.html

Why might this be relevant

The combinators below combine two (or more) streams by polling one of them in each call to poll/poll_next. This is generally fine, if the executor regularly polls the futures/streams. However when the futures inside the stream relies on the above cited guarantee of invocation after waking something could break in the futures inside the stream.

For example consider the following situation:

As far as I can tell, this could lead to unnecessary delays in future completion and breaks (or at least loosens) the guarantees given by Waker. From the viewpoint of the futures in A, this basically breaks the guarantees of wake().

Affected combinators (likely incomplete list)

Not affected (as it polls all futures/streams)


If this is not a problem please explain why, I'm trying to understand the details of how executor, streams and futures interact.