time: do not panic on timeout(Duration::MAX) (#3551)

It is tempting to use very large `Duration` value to get a practically
infinite timeout.

Before this commit Tokio panics on checked Instant + Duration
overflow.

This commit implements very simple fix: if Instant + Duration
overflows, we use duration = 30 years. Better fix should avoid
firing a timer on duration overflow. It requires deeper understanding
how timers work, but also it is not clear, for example, what
`Sleep::deadline` function should return.

Similar fix is done for `sleep`.
This commit is contained in:
Stepan Koltsov
2021-02-26 10:04:08 +01:00
committed by GitHub
parent 5756a005a6
commit d2ad7afd21
4 changed files with 48 additions and 2 deletions
+27
View File
@@ -74,6 +74,33 @@ async fn future_and_timeout_in_future() {
assert_ready_ok!(fut.poll()).unwrap();
}
#[tokio::test]
async fn very_large_timeout() {
time::pause();
// Not yet complete
let (tx, rx) = oneshot::channel();
// copy-paste unstable `Duration::MAX`
let duration_max = Duration::from_secs(u64::MAX) + Duration::from_nanos(999_999_999);
// Wrap it with a deadline
let mut fut = task::spawn(timeout(duration_max, rx));
// Ready!
assert_pending!(fut.poll());
// Turn the timer, it runs for the elapsed time
time::advance(Duration::from_secs(86400 * 365 * 10)).await;
assert_pending!(fut.poll());
// Complete the future
tx.send(()).unwrap();
assert_ready_ok!(fut.poll()).unwrap();
}
#[tokio::test]
async fn deadline_now_elapses() {
use futures::future::pending;