diff --git a/tokio/src/runtime/time_alt/entry.rs b/tokio/src/runtime/time_alt/entry.rs index b7b5627e0..f9a4746b8 100644 --- a/tokio/src/runtime/time_alt/entry.rs +++ b/tokio/src/runtime/time_alt/entry.rs @@ -228,11 +228,16 @@ impl Handle { } } - pub(crate) fn register_waker(&self, waker: Waker) { + pub(crate) fn register_waker(&self, waker: &Waker) { let mut lock = self.entry.state.lock(); if !lock.cancelled && !lock.woken_up { - let maybe_old_waker = lock.waker.replace(waker); - // unlock before calling waker + // PANIC: no intermediary state is possible should the user-controllable `Waker` + // panic on `Clone` or `Drop`. + let maybe_old_waker = match &lock.waker { + Some(current_waker) if current_waker.will_wake(waker) => None, + _ => lock.waker.replace(waker.clone()), + }; + // unlock before dropping waker drop(lock); drop(maybe_old_waker); } diff --git a/tokio/src/runtime/time_alt/timer.rs b/tokio/src/runtime/time_alt/timer.rs index 178ab81f2..eb1505fd0 100644 --- a/tokio/src/runtime/time_alt/timer.rs +++ b/tokio/src/runtime/time_alt/timer.rs @@ -97,7 +97,7 @@ impl Timer { match self.entry.as_ref() { Some(entry) if entry.is_woken_up() => Poll::Ready(()), Some(entry) => { - entry.register_waker(cx.waker().clone()); + entry.register_waker(cx.waker()); Poll::Pending } None => self.register(cx),