From 482eaddec0347431b37566b45a63f2be62db5ab4 Mon Sep 17 00:00:00 2001 From: Patrick Ribbsaeter Date: Tue, 13 Oct 2026 16:21:46 +0200 Subject: [PATCH] runtime: record time wake when unparking tasks on current thread (#8595) Fixes #8232. Signed-off-by: Patrick Ribbsaeter --- tokio/src/runtime/driver.rs | 7 ++++ .../runtime/scheduler/current_thread/mod.rs | 5 ++- tokio/tests/time_pause.rs | 41 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/tokio/src/runtime/driver.rs b/tokio/src/runtime/driver.rs index 92b2350..9fc1625 100644 --- a/tokio/src/runtime/driver.rs +++ b/tokio/src/runtime/driver.rs @@ -86,6 +86,13 @@ impl Handle { self.io.unpark(); } + pub(crate) fn unpark_self(&self) { + #[cfg(feature = "time")] + if let Some(handle) = &self.time { + handle.unpark(); + } + } + cfg_io_driver! { #[track_caller] pub(crate) fn io(&self) -> &crate::runtime::io::Handle { diff --git a/tokio/src/runtime/scheduler/current_thread/mod.rs b/tokio/src/runtime/scheduler/current_thread/mod.rs index 01108de..2a8805d 100644 --- a/tokio/src/runtime/scheduler/current_thread/mod.rs +++ b/tokio/src/runtime/scheduler/current_thread/mod.rs @@ -682,6 +682,7 @@ impl Schedule for Arc { if let Some(core) = core.as_mut() { core.push_task(self, task); } + self.driver.unpark_self(); } _ => { // Track that a task was scheduled from **outside** of the runtime. @@ -748,7 +749,9 @@ impl Wake for Handle { // If we are already running on the runtime, then it's not required to wake up the // runtime. context::with_scheduler(|maybe_cx| match maybe_cx { - Some(CurrentThread(cx)) if Arc::ptr_eq(arc_self, &cx.handle) => {} + Some(CurrentThread(cx)) if Arc::ptr_eq(arc_self, &cx.handle) => { + arc_self.driver.unpark_self(); + } _ => { arc_self.driver.unpark(); } diff --git a/tokio/tests/time_pause.rs b/tokio/tests/time_pause.rs index be993b4..61890ed 100644 --- a/tokio/tests/time_pause.rs +++ b/tokio/tests/time_pause.rs @@ -331,3 +331,44 @@ fn poll_next(interval: &mut task::Spawn) -> Poll { fn ms(n: u64) -> Duration { Duration::from_millis(n) } + +#[cfg(all(feature = "full", unix))] +#[tokio::test(start_paused = true)] +async fn paused_time_join_unix_datagram_and_sleep() { + use tokio::net::UnixDatagram; + + let time = Instant::now(); + let (sock1, sock2) = UnixDatagram::pair().unwrap(); + let mut buf = [0u8; 1]; + tokio::join!( + async { + sock1.send(&[1u8]).await.unwrap(); + time::sleep(Duration::from_millis(100)).await; + }, + async { + sock2.recv(&mut buf).await.unwrap(); + assert_eq!(time.elapsed(), Duration::ZERO); + }, + ); +} + +#[cfg(all(feature = "full", unix))] +#[tokio::test(start_paused = true)] +async fn paused_time_spawn_unix_datagram_and_sleep() { + use tokio::net::UnixDatagram; + + let time = Instant::now(); + let (sock1, sock2) = UnixDatagram::pair().unwrap(); + + sock1.send(&[1u8]).await.unwrap(); + + let h = tokio::spawn(async move { + let mut buf = [0u8; 1]; + sock2.recv(&mut buf).await.unwrap(); + assert_eq!(time.elapsed(), Duration::ZERO); + }); + + time::sleep(Duration::from_millis(100)).await; + h.await.unwrap(); + assert_eq!(time.elapsed(), Duration::from_millis(100)); +} -- 2.55.0.windows.3