From dc39161eb76279fdc9b1cfcefa305aab4ae0de8e Mon Sep 17 00:00:00 2001 From: Seth Brown Date: Thu, 6 May 2021 16:42:14 -0600 Subject: [PATCH 1/2] time: document auto-advancing behavior of runtime When there is no work for the runtime to do and the clock is paused, it is advanced to the closest timer. This can be confusing, so this commit documents that behavior. --- tokio/src/time/clock.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tokio/src/time/clock.rs b/tokio/src/time/clock.rs index c5ef86be4e0..1902a491a9c 100644 --- a/tokio/src/time/clock.rs +++ b/tokio/src/time/clock.rs @@ -85,6 +85,18 @@ cfg_test_util! { /// /// Panics if time is already frozen or if called from outside of a /// `current_thread` Tokio runtime. + /// + /// # Auto-advance + /// + /// If time is paused, when the runtime has no work to do, the clock is + /// auto-advanced to the closest pending timer. This can cause some + /// confusion, because if a [`Sleep`] (or other timer-backed primitive) is + /// `.await`ed, the timer is set forward unexpectedly. However, this + /// behavior is necessary because there could be situations in which the + /// runtime hangs because the clock never gets advanced, so a timer never + /// resolves. + /// + /// [`Sleep`]: crate::time::Sleep pub fn pause() { let clock = clock().expect("time cannot be frozen from outside the Tokio runtime"); clock.pause(); @@ -119,11 +131,20 @@ cfg_test_util! { /// /// Panics if time is not frozen or if called from outside of the Tokio /// runtime. + /// + /// # Auto-advance + /// + /// If the time is paused and there is no work to do, the runtime advances + /// time to the next-closest timer, which may cause confusion. See + /// [`pause`](pause#auto-advance) for more details. pub async fn advance(duration: Duration) { let clock = clock().expect("time cannot be frozen from outside the Tokio runtime"); let until = clock.now() + duration; clock.advance(duration); + // Prevent the runtime from advancing the clock to the next pending + // timer when parking, which likely will advance it too far (see + // https://github.com/tokio-rs/tokio/pull/3712) crate::time::sleep_until(until).await; } From 415cce47f5b2eac809fa5de42a1cd302719015f1 Mon Sep 17 00:00:00 2001 From: sb64 <53383020+sb64@users.noreply.github.com> Date: Wed, 26 May 2021 10:58:03 -0600 Subject: [PATCH 2/2] Remove unnecessary statements Co-authored-by: Alice Ryhl --- tokio/src/time/clock.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tokio/src/time/clock.rs b/tokio/src/time/clock.rs index 1902a491a9c..156144539a3 100644 --- a/tokio/src/time/clock.rs +++ b/tokio/src/time/clock.rs @@ -88,13 +88,10 @@ cfg_test_util! { /// /// # Auto-advance /// - /// If time is paused, when the runtime has no work to do, the clock is - /// auto-advanced to the closest pending timer. This can cause some - /// confusion, because if a [`Sleep`] (or other timer-backed primitive) is - /// `.await`ed, the timer is set forward unexpectedly. However, this - /// behavior is necessary because there could be situations in which the - /// runtime hangs because the clock never gets advanced, so a timer never - /// resolves. + /// If time is paused and the runtime has no work to do, the clock is + /// auto-advanced to the next pending timer. This means that [`Sleep`] or + /// other timer-backed primitives can cause the runtime to advance the + /// current time when awaited. /// /// [`Sleep`]: crate::time::Sleep pub fn pause() { @@ -135,8 +132,8 @@ cfg_test_util! { /// # Auto-advance /// /// If the time is paused and there is no work to do, the runtime advances - /// time to the next-closest timer, which may cause confusion. See - /// [`pause`](pause#auto-advance) for more details. + /// time to the next timer. See [`pause`](pause#auto-advance) for more + /// details. pub async fn advance(duration: Duration) { let clock = clock().expect("time cannot be frozen from outside the Tokio runtime"); let until = clock.now() + duration;