diff --git a/src/shims/time.rs b/src/shims/time.rs index a2cbd84bc2d..d9edbe3d7bd 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -210,7 +210,11 @@ fn nanosleep( return Ok(-1); } }; - let timeout_time = Time::Monotonic(Instant::now().checked_add(duration).unwrap()); + // If adding the duration overflows, let's just sleep for an hour. Waking up early is always acceptable. + let timeout_time = Instant::now() + .checked_add(duration) + .unwrap_or_else(|| Instant::now().checked_add(Duration::from_secs(3600)).unwrap()); + let timeout_time = Time::Monotonic(timeout_time); let active_thread = this.get_active_thread(); this.block_thread(active_thread); diff --git a/tests/pass/sleep_long.rs b/tests/pass/sleep_long.rs new file mode 100644 index 00000000000..dd4a1843942 --- /dev/null +++ b/tests/pass/sleep_long.rs @@ -0,0 +1,18 @@ +//@ignore-target-windows: no threads nor sleep on Windows +//@compile-flags: -Zmiri-ignore-leaks -Zmiri-disable-isolation +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; + +fn main() { + let finished = Arc::new(Mutex::new(false)); + let t_finished = finished.clone(); + thread::spawn(move || { + // Sleep very, very long. + thread::sleep(Duration::new(u64::MAX, 0)); + *t_finished.lock().unwrap() = true; + }); + thread::sleep(Duration::from_millis(100)); + assert_eq!(*finished.lock().unwrap(), false); + // Stopping the main thread will also kill the sleeper. +}