From 5af1f52cf628374581b8a8279a6e78fcd8ed2d07 Mon Sep 17 00:00:00 2001 From: Spencer Judge Date: Sat, 20 Aug 2022 23:11:24 -0700 Subject: [PATCH 1/3] Fix incorrect termination of `select_with_strategy` streams (#2635) --- .../src/stream/select_with_strategy.rs | 11 +++-- futures/tests/stream.rs | 42 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/futures-util/src/stream/select_with_strategy.rs b/futures-util/src/stream/select_with_strategy.rs index 7423519df1..224d5f821c 100644 --- a/futures-util/src/stream/select_with_strategy.rs +++ b/futures-util/src/stream/select_with_strategy.rs @@ -231,18 +231,23 @@ where St1: Stream, St2: Stream, { - match poll_side(select, side, cx) { + let first_done = match poll_side(select, side, cx) { Poll::Ready(Some(item)) => return Poll::Ready(Some(item)), Poll::Ready(None) => { select.internal_state.finish(side); + true } - Poll::Pending => (), + Poll::Pending => false, }; let other = side.other(); match poll_side(select, other, cx) { Poll::Ready(None) => { select.internal_state.finish(other); - Poll::Ready(None) + if first_done { + Poll::Ready(None) + } else { + Poll::Pending + } } a => a, } diff --git a/futures/tests/stream.rs b/futures/tests/stream.rs index 71ec654bfb..5cde45833f 100644 --- a/futures/tests/stream.rs +++ b/futures/tests/stream.rs @@ -1,5 +1,9 @@ +use std::cell::Cell; use std::iter; +use std::pin::Pin; +use std::rc::Rc; use std::sync::Arc; +use std::task::Context; use futures::channel::mpsc; use futures::executor::block_on; @@ -9,6 +13,7 @@ use futures::sink::SinkExt; use futures::stream::{self, StreamExt}; use futures::task::Poll; use futures::{ready, FutureExt}; +use futures_core::Stream; use futures_test::task::noop_context; #[test] @@ -419,3 +424,40 @@ fn ready_chunks() { assert_eq!(s.next().await.unwrap(), vec![4]); }); } + +struct SlowStream { + times_should_poll: usize, + times_polled: Rc>, +} +impl Stream for SlowStream { + type Item = usize; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + self.times_polled.set(self.times_polled.get() + 1); + if self.times_polled.get() % 2 == 0 { + cx.waker().wake_by_ref(); + return Poll::Pending; + } + if self.times_polled.get() >= self.times_should_poll { + return Poll::Ready(None); + } + Poll::Ready(Some(self.times_polled.get())) + } +} + +#[test] +fn select_with_strategy_doesnt_terminate_early() { + for side in [stream::PollNext::Left, stream::PollNext::Right] { + let times_should_poll = 10; + let count = Rc::new(Cell::new(0)); + let b = stream::iter([10, 20]); + + let mut selected = stream::select_with_strategy( + SlowStream { times_should_poll, times_polled: count.clone() }, + b, + |_: &mut ()| side, + ); + block_on(async move { while selected.next().await.is_some() {} }); + assert_eq!(count.get(), times_should_poll + 1); + } +} From 12bafb108adfeeece613674f8984c12ed893445f Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 24 Aug 2022 01:30:36 +0000 Subject: [PATCH 2/3] Update no_atomic_cas.rs --- no_atomic_cas.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/no_atomic_cas.rs b/no_atomic_cas.rs index 341e6ac7d2..629d3260d4 100644 --- a/no_atomic_cas.rs +++ b/no_atomic_cas.rs @@ -2,6 +2,7 @@ // It is not intended for manual editing. const NO_ATOMIC_CAS: &[&str] = &[ + "armv4t-none-eabi", "avr-unknown-gnu-atmega328", "bpfeb-unknown-none", "bpfel-unknown-none", From c1e9f08ad53f447881d5c9dcc935d195a19a2575 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Mon, 29 Aug 2022 22:19:29 +0900 Subject: [PATCH 3/3] Release 0.3.24 --- CHANGELOG.md | 4 ++++ futures-channel/Cargo.toml | 6 +++--- futures-core/Cargo.toml | 2 +- futures-executor/Cargo.toml | 8 ++++---- futures-io/Cargo.toml | 2 +- futures-macro/Cargo.toml | 2 +- futures-sink/Cargo.toml | 2 +- futures-task/Cargo.toml | 2 +- futures-test/Cargo.toml | 16 ++++++++-------- futures-util/Cargo.toml | 14 +++++++------- futures/Cargo.toml | 16 ++++++++-------- 11 files changed, 39 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f71c775f5d..f479bce0c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.3.24 - 2022-08-29 + +* Fix incorrect termination of `select_with_strategy` streams (#2635) + # 0.3.23 - 2022-08-14 * Work around MSRV increase due to a cargo bug. diff --git a/futures-channel/Cargo.toml b/futures-channel/Cargo.toml index 7ecc92372e..09dbfe693e 100644 --- a/futures-channel/Cargo.toml +++ b/futures-channel/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-channel" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" @@ -22,8 +22,8 @@ unstable = [] cfg-target-has-atomic = [] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.23", default-features = false } -futures-sink = { path = "../futures-sink", version = "0.3.23", default-features = false, optional = true } +futures-core = { path = "../futures-core", version = "0.3.24", default-features = false } +futures-sink = { path = "../futures-sink", version = "0.3.24", default-features = false, optional = true } [dev-dependencies] futures = { path = "../futures", default-features = true } diff --git a/futures-core/Cargo.toml b/futures-core/Cargo.toml index 51acc3ee97..e5846c8815 100644 --- a/futures-core/Cargo.toml +++ b/futures-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-core" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.36" license = "MIT OR Apache-2.0" diff --git a/futures-executor/Cargo.toml b/futures-executor/Cargo.toml index b954d09160..b2ba996511 100644 --- a/futures-executor/Cargo.toml +++ b/futures-executor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-executor" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" @@ -16,9 +16,9 @@ std = ["futures-core/std", "futures-task/std", "futures-util/std"] thread-pool = ["std", "num_cpus"] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.23", default-features = false } -futures-task = { path = "../futures-task", version = "0.3.23", default-features = false } -futures-util = { path = "../futures-util", version = "0.3.23", default-features = false } +futures-core = { path = "../futures-core", version = "0.3.24", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.24", default-features = false } +futures-util = { path = "../futures-util", version = "0.3.24", default-features = false } num_cpus = { version = "1.8.0", optional = true } [dev-dependencies] diff --git a/futures-io/Cargo.toml b/futures-io/Cargo.toml index 9543b3e4ef..0600ac1b07 100644 --- a/futures-io/Cargo.toml +++ b/futures-io/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-io" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.36" license = "MIT OR Apache-2.0" diff --git a/futures-macro/Cargo.toml b/futures-macro/Cargo.toml index f533a3dd8a..48d6478f2d 100644 --- a/futures-macro/Cargo.toml +++ b/futures-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-macro" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" diff --git a/futures-sink/Cargo.toml b/futures-sink/Cargo.toml index 27869e50f2..5ac760d092 100644 --- a/futures-sink/Cargo.toml +++ b/futures-sink/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-sink" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.36" license = "MIT OR Apache-2.0" diff --git a/futures-task/Cargo.toml b/futures-task/Cargo.toml index e558ca373d..9869aa5737 100644 --- a/futures-task/Cargo.toml +++ b/futures-task/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-task" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" diff --git a/futures-test/Cargo.toml b/futures-test/Cargo.toml index 3115a4d125..35f39d5363 100644 --- a/futures-test/Cargo.toml +++ b/futures-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-test" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" @@ -11,13 +11,13 @@ Common utilities for testing components built off futures-rs. """ [dependencies] -futures-core = { version = "0.3.23", path = "../futures-core", default-features = false } -futures-task = { version = "0.3.23", path = "../futures-task", default-features = false } -futures-io = { version = "0.3.23", path = "../futures-io", default-features = false } -futures-util = { version = "0.3.23", path = "../futures-util", default-features = false } -futures-executor = { version = "0.3.23", path = "../futures-executor", default-features = false } -futures-sink = { version = "0.3.23", path = "../futures-sink", default-features = false } -futures-macro = { version = "=0.3.23", path = "../futures-macro", default-features = false } +futures-core = { version = "0.3.24", path = "../futures-core", default-features = false } +futures-task = { version = "0.3.24", path = "../futures-task", default-features = false } +futures-io = { version = "0.3.24", path = "../futures-io", default-features = false } +futures-util = { version = "0.3.24", path = "../futures-util", default-features = false } +futures-executor = { version = "0.3.24", path = "../futures-executor", default-features = false } +futures-sink = { version = "0.3.24", path = "../futures-sink", default-features = false } +futures-macro = { version = "=0.3.24", path = "../futures-macro", default-features = false } pin-utils = { version = "0.1.0", default-features = false } pin-project = "1.0.11" diff --git a/futures-util/Cargo.toml b/futures-util/Cargo.toml index bbf90597d8..c5a9b01c6f 100644 --- a/futures-util/Cargo.toml +++ b/futures-util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures-util" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" @@ -34,12 +34,12 @@ write-all-vectored = ["io"] cfg-target-has-atomic = [] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.23", default-features = false } -futures-task = { path = "../futures-task", version = "0.3.23", default-features = false } -futures-channel = { path = "../futures-channel", version = "0.3.23", default-features = false, features = ["std"], optional = true } -futures-io = { path = "../futures-io", version = "0.3.23", default-features = false, features = ["std"], optional = true } -futures-sink = { path = "../futures-sink", version = "0.3.23", default-features = false, optional = true } -futures-macro = { path = "../futures-macro", version = "=0.3.23", default-features = false, optional = true } +futures-core = { path = "../futures-core", version = "0.3.24", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.24", default-features = false } +futures-channel = { path = "../futures-channel", version = "0.3.24", default-features = false, features = ["std"], optional = true } +futures-io = { path = "../futures-io", version = "0.3.24", default-features = false, features = ["std"], optional = true } +futures-sink = { path = "../futures-sink", version = "0.3.24", default-features = false, optional = true } +futures-macro = { path = "../futures-macro", version = "=0.3.24", default-features = false, optional = true } slab = { version = "0.4.2", optional = true } memchr = { version = "2.2", optional = true } futures_01 = { version = "0.1.25", optional = true, package = "futures" } diff --git a/futures/Cargo.toml b/futures/Cargo.toml index 421e3e065d..cab5b05de3 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "futures" -version = "0.3.23" +version = "0.3.24" edition = "2018" rust-version = "1.45" license = "MIT OR Apache-2.0" @@ -15,13 +15,13 @@ composability, and iterator-like interfaces. categories = ["asynchronous"] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.23", default-features = false } -futures-task = { path = "../futures-task", version = "0.3.23", default-features = false } -futures-channel = { path = "../futures-channel", version = "0.3.23", default-features = false, features = ["sink"] } -futures-executor = { path = "../futures-executor", version = "0.3.23", default-features = false, optional = true } -futures-io = { path = "../futures-io", version = "0.3.23", default-features = false } -futures-sink = { path = "../futures-sink", version = "0.3.23", default-features = false } -futures-util = { path = "../futures-util", version = "0.3.23", default-features = false, features = ["sink"] } +futures-core = { path = "../futures-core", version = "0.3.24", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.24", default-features = false } +futures-channel = { path = "../futures-channel", version = "0.3.24", default-features = false, features = ["sink"] } +futures-executor = { path = "../futures-executor", version = "0.3.24", default-features = false, optional = true } +futures-io = { path = "../futures-io", version = "0.3.24", default-features = false } +futures-sink = { path = "../futures-sink", version = "0.3.24", default-features = false } +futures-util = { path = "../futures-util", version = "0.3.24", default-features = false, features = ["sink"] } [dev-dependencies] futures-executor = { path = "../futures-executor", features = ["thread-pool"] }