From b1bdb3c57b9adfa928644ece1da97860c558efbb Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 17 May 2025 11:24:36 +0200 Subject: [PATCH 1/3] ci: update macros_type_mismatch for Rust 1.87.0 (#7339) (cherry picked from commit a48e418dcbbe7eccc7ea0f0071ca60aca21a61b7) --- tests-build/tests/fail/macros_type_mismatch.stderr | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests-build/tests/fail/macros_type_mismatch.stderr b/tests-build/tests/fail/macros_type_mismatch.stderr index 201df9cdd..f9c32f005 100644 --- a/tests-build/tests/fail/macros_type_mismatch.stderr +++ b/tests-build/tests/fail/macros_type_mismatch.stderr @@ -57,8 +57,6 @@ error[E0277]: the `?` operator can only be used in an async block that returns ` 39 | async fn question_mark_operator_with_invalid_option() -> Option<()> { 40 | None?; | ^ cannot use the `?` operator in an async block that returns `()` - | - = help: the trait `FromResidual>` is not implemented for `()` error[E0308]: mismatched types --> tests/fail/macros_type_mismatch.rs:40:5 @@ -87,8 +85,6 @@ error[E0277]: the `?` operator can only be used in an async block that returns ` 56 | async fn question_mark_operator_with_invalid_result() -> Result<(), ()> { 57 | Ok(())?; | ^ cannot use the `?` operator in an async block that returns `()` - | - = help: the trait `FromResidual>` is not implemented for `()` error[E0308]: mismatched types --> tests/fail/macros_type_mismatch.rs:57:5 From 421a7b001c762a25c0b009c9ffb86f0661608f90 Mon Sep 17 00:00:00 2001 From: Jason Gin <67525213+GJason88@users.noreply.github.com> Date: Fri, 23 May 2025 15:12:28 -0400 Subject: [PATCH 2/3] rt: do not track time-based metrics on wasm32-unknown-unknown (#7322) --- tokio/src/net/tcp/stream.rs | 10 +++++- tokio/src/runtime/builder.rs | 2 ++ tokio/src/runtime/metrics/batch.rs | 54 ++++++++++++++++++++--------- tokio/tests/tcp_shutdown.rs | 55 +++++++++++++++++++++++++++++- 4 files changed, 103 insertions(+), 18 deletions(-) diff --git a/tokio/src/net/tcp/stream.rs b/tokio/src/net/tcp/stream.rs index b0e3ec27c..f64a526b4 100644 --- a/tokio/src/net/tcp/stream.rs +++ b/tokio/src/net/tcp/stream.rs @@ -1112,8 +1112,16 @@ impl TcpStream { /// This function will cause all pending and future I/O on the specified /// portions to return immediately with an appropriate value (see the /// documentation of `Shutdown`). + /// + /// Remark: this function transforms `Err(std::io::ErrorKind::NotConnected)` to `Ok(())`. + /// It does this to abstract away OS specific logic and to prevent a race condition between + /// this function call and the OS closing this socket because of external events (e.g. TCP reset). + /// See for more information. pub(super) fn shutdown_std(&self, how: Shutdown) -> io::Result<()> { - self.io.shutdown(how) + match self.io.shutdown(how) { + Err(err) if err.kind() == std::io::ErrorKind::NotConnected => Ok(()), + result => result, + } } /// Gets the value of the `TCP_NODELAY` option on this socket. diff --git a/tokio/src/runtime/builder.rs b/tokio/src/runtime/builder.rs index 47ba18c96..93c67c5b5 100644 --- a/tokio/src/runtime/builder.rs +++ b/tokio/src/runtime/builder.rs @@ -770,6 +770,7 @@ impl Builder { /// # } /// ``` #[cfg(tokio_unstable)] + #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))] pub fn on_before_task_poll(&mut self, f: F) -> &mut Self where F: Fn(&TaskMeta<'_>) + Send + Sync + 'static, @@ -813,6 +814,7 @@ impl Builder { /// # } /// ``` #[cfg(tokio_unstable)] + #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))] pub fn on_after_task_poll(&mut self, f: F) -> &mut Self where F: Fn(&TaskMeta<'_>) + Send + Sync + 'static, diff --git a/tokio/src/runtime/metrics/batch.rs b/tokio/src/runtime/metrics/batch.rs index 00f9c9898..fe2f4a9da 100644 --- a/tokio/src/runtime/metrics/batch.rs +++ b/tokio/src/runtime/metrics/batch.rs @@ -12,7 +12,7 @@ pub(crate) struct MetricsBatch { busy_duration_total: u64, /// Instant at which work last resumed (continued after park). - processing_scheduled_tasks_started_at: Instant, + processing_scheduled_tasks_started_at: Option, /// Number of times the worker parked. park_count: u64, @@ -67,17 +67,17 @@ cfg_unstable_metrics! { impl MetricsBatch { pub(crate) fn new(worker_metrics: &WorkerMetrics) -> MetricsBatch { - let now = Instant::now(); - Self::new_unstable(worker_metrics, now) + let maybe_now = now(); + Self::new_unstable(worker_metrics, maybe_now) } cfg_metrics_variant! { stable: { #[inline(always)] - fn new_unstable(_worker_metrics: &WorkerMetrics, now: Instant) -> MetricsBatch { + fn new_unstable(_worker_metrics: &WorkerMetrics, maybe_now: Option) -> MetricsBatch { MetricsBatch { busy_duration_total: 0, - processing_scheduled_tasks_started_at: now, + processing_scheduled_tasks_started_at: maybe_now, park_count: 0, park_unpark_count: 0, } @@ -85,7 +85,16 @@ impl MetricsBatch { }, unstable: { #[inline(always)] - fn new_unstable(worker_metrics: &WorkerMetrics, now: Instant) -> MetricsBatch { + fn new_unstable(worker_metrics: &WorkerMetrics, maybe_now: Option) -> MetricsBatch { + let poll_timer = maybe_now.and_then(|now| { + worker_metrics + .poll_count_histogram + .as_ref() + .map(|worker_poll_counts| PollTimer { + poll_counts: HistogramBatch::from_histogram(worker_poll_counts), + poll_started_at: now, + }) + }); MetricsBatch { park_count: 0, park_unpark_count: 0, @@ -97,13 +106,8 @@ impl MetricsBatch { local_schedule_count: 0, overflow_count: 0, busy_duration_total: 0, - processing_scheduled_tasks_started_at: now, - poll_timer: worker_metrics.poll_count_histogram.as_ref().map( - |worker_poll_counts| PollTimer { - poll_counts: HistogramBatch::from_histogram(worker_poll_counts), - poll_started_at: now, - }, - ), + processing_scheduled_tasks_started_at: maybe_now, + poll_timer, } } } @@ -186,13 +190,17 @@ impl MetricsBatch { /// Start processing a batch of tasks pub(crate) fn start_processing_scheduled_tasks(&mut self) { - self.processing_scheduled_tasks_started_at = Instant::now(); + self.processing_scheduled_tasks_started_at = now(); } /// Stop processing a batch of tasks pub(crate) fn end_processing_scheduled_tasks(&mut self) { - let busy_duration = self.processing_scheduled_tasks_started_at.elapsed(); - self.busy_duration_total += duration_as_u64(busy_duration); + if let Some(processing_scheduled_tasks_started_at) = + self.processing_scheduled_tasks_started_at + { + let busy_duration = processing_scheduled_tasks_started_at.elapsed(); + self.busy_duration_total += duration_as_u64(busy_duration); + } } cfg_metrics_variant! { @@ -279,3 +287,17 @@ cfg_rt_multi_thread! { pub(crate) fn duration_as_u64(dur: Duration) -> u64 { u64::try_from(dur.as_nanos()).unwrap_or(u64::MAX) } + +/// Gate unsupported time metrics for `wasm32-unknown-unknown` +/// +fn now() -> Option { + if cfg!(all( + target_arch = "wasm32", + target_os = "unknown", + target_vendor = "unknown" + )) { + None + } else { + Some(Instant::now()) + } +} diff --git a/tokio/tests/tcp_shutdown.rs b/tokio/tests/tcp_shutdown.rs index 2497c1a40..837e61230 100644 --- a/tokio/tests/tcp_shutdown.rs +++ b/tokio/tests/tcp_shutdown.rs @@ -2,8 +2,10 @@ #![cfg(all(feature = "full", not(target_os = "wasi"), not(miri)))] // Wasi doesn't support bind // No `socket` on miri. +use std::time::Duration; use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; use tokio::net::{TcpListener, TcpStream}; +use tokio::sync::oneshot::channel; use tokio_test::assert_ok; #[tokio::test] @@ -11,7 +13,7 @@ async fn shutdown() { let srv = assert_ok!(TcpListener::bind("127.0.0.1:0").await); let addr = assert_ok!(srv.local_addr()); - tokio::spawn(async move { + let handle = tokio::spawn(async move { let mut stream = assert_ok!(TcpStream::connect(&addr).await); assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); @@ -26,4 +28,55 @@ async fn shutdown() { let n = assert_ok!(io::copy(&mut rd, &mut wr).await); assert_eq!(n, 0); + assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); + handle.await.unwrap() +} + +#[tokio::test] +async fn shutdown_after_tcp_reset() { + let srv = assert_ok!(TcpListener::bind("127.0.0.1:0").await); + let addr = assert_ok!(srv.local_addr()); + + let (connected_tx, connected_rx) = channel(); + let (dropped_tx, dropped_rx) = channel(); + + let handle = tokio::spawn(async move { + let mut stream = assert_ok!(TcpStream::connect(&addr).await); + connected_tx.send(()).unwrap(); + + dropped_rx.await.unwrap(); + assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); + }); + + let (stream, _) = assert_ok!(srv.accept().await); + // By setting linger to 0 we will trigger a TCP reset + stream.set_linger(Some(Duration::new(0, 0))).unwrap(); + connected_rx.await.unwrap(); + + drop(stream); + dropped_tx.send(()).unwrap(); + + handle.await.unwrap(); +} + +#[tokio::test] +async fn shutdown_multiple_calls() { + let srv = assert_ok!(TcpListener::bind("127.0.0.1:0").await); + let addr = assert_ok!(srv.local_addr()); + + let (connected_tx, connected_rx) = channel(); + + let handle = tokio::spawn(async move { + let mut stream = assert_ok!(TcpStream::connect(&addr).await); + connected_tx.send(()).unwrap(); + assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); + assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); + assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); + }); + + let (mut stream, _) = assert_ok!(srv.accept().await); + connected_rx.await.unwrap(); + + assert_ok!(AsyncWriteExt::shutdown(&mut stream).await); + handle.await.unwrap(); } From 3768696d92d403d98b7d559934617890f882ec02 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 24 May 2025 07:27:50 -0700 Subject: [PATCH 3/3] chore: prepare Tokio v1.45.1 (#7359) --- README.md | 2 +- tokio/CHANGELOG.md | 12 ++++++++++++ tokio/Cargo.toml | 2 +- tokio/README.md | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 830efafb5..8e4fa0564 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Make sure you activated the full features of the tokio crate on Cargo.toml: ```toml [dependencies] -tokio = { version = "1.45.0", features = ["full"] } +tokio = { version = "1.45.1", features = ["full"] } ``` Then, on your main.rs: diff --git a/tokio/CHANGELOG.md b/tokio/CHANGELOG.md index 2d2f94ba0..27f84c867 100644 --- a/tokio/CHANGELOG.md +++ b/tokio/CHANGELOG.md @@ -1,3 +1,15 @@ +# 1.45.1 (May 24th, 2025) + +This fixes a regression on the wasm32-unknown-unknown target, where code that +previously did not panic due to calls to `Instant::now()` started failing. This +is due to the stabilization of the first time-based metric. + +### Fixed + +- Disable time-based metrics on wasm32-unknown-unknown ([#7322]) + +[#7322]: https://github.com/tokio-rs/tokio/pull/7322 + # 1.45.0 (May 5th, 2025) ### Added diff --git a/tokio/Cargo.toml b/tokio/Cargo.toml index 44eb58d40..a8b03b906 100644 --- a/tokio/Cargo.toml +++ b/tokio/Cargo.toml @@ -6,7 +6,7 @@ name = "tokio" # - README.md # - Update CHANGELOG.md. # - Create "v1.x.y" git tag. -version = "1.45.0" +version = "1.45.1" edition = "2021" rust-version = "1.70" authors = ["Tokio Contributors "] diff --git a/tokio/README.md b/tokio/README.md index 830efafb5..8e4fa0564 100644 --- a/tokio/README.md +++ b/tokio/README.md @@ -56,7 +56,7 @@ Make sure you activated the full features of the tokio crate on Cargo.toml: ```toml [dependencies] -tokio = { version = "1.45.0", features = ["full"] } +tokio = { version = "1.45.1", features = ["full"] } ``` Then, on your main.rs: