Skip to content

Commit c4797c0

Browse files
fix: manual timer deadline resolution (#1273)
It seems sometimes Tokio's timer wheel may not advance (if the executor is blocked) causing `Sleep` future to take more ticks to be woken up and be `Poll::Ready` even after deadline passes. This fix adds an early deadline check in `MutableSleep::poll_ready`. ```js let ticked = false; setTimeout(() => { console.log("timer done"); ticked = true; }, 1); const now = Date.now(); while (Date.now() - now < 2); setImmediate(() => { console.log(ticked); // true }); ``` --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
1 parent 6d7de19 commit c4797c0

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

core/web_timeout.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,19 @@ impl MutableSleep {
180180
if !external.will_wake(waker) {
181181
external.clone_from(waker);
182182
}
183+
184+
// We do a manual deadline check here. Tokio's timer wheel may not immediately check the deadline if the
185+
// executor was blocked.
186+
// Skip this check under Miri as it interferes with time simulation.
187+
#[cfg(not(miri))]
188+
{
189+
let sleep = unsafe { self.sleep.get().as_mut().unwrap_unchecked() };
190+
if let Some(sleep) = sleep
191+
&& Instant::now() >= sleep.deadline()
192+
{
193+
return Poll::Ready(());
194+
}
195+
}
183196
Poll::Pending
184197
} else {
185198
*external = Some(cx.waker().clone());

0 commit comments

Comments
 (0)