Description
The following program:
fn main() {
let t = std::time::Instant::now();
let d = std::time::Duration::from_secs(60);
eprintln!("{:?}", (t - d).elapsed());
}
works on Linux, but could panic on Mac. The reason for that is that, as implemented, Instant
on mac starts at zero at reboot, so it can't represent times before the machine started.
This is pretty unfortunate -- it means that impl Sub<Duration> for Instant
isn't really usable on mac, as subtracting even a small duration can panic. And subtracing duration is pretty useful and natural too implement tasks like "periodically, cleanup data crated earlier than Instant::now() - Duration::from_secs(60)
".
While technically we don't give any guarantees on Instant
range and document this as system-dependent, it is really unfortunate that subtracting API exists, works fine on Linux, and fails occasionally on macs. I think we should just go and patch the time on our side, to get some sort of a reasonable range bothways.
I think just
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index f99c453a3a8..994320564c4 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -168,7 +168,7 @@ pub fn now() -> Instant {
extern "C" {
fn mach_absolute_time() -> u64;
}
- Instant { t: unsafe { mach_absolute_time() } }
+ Instant { t: unsafe { mach_absolute_time() } + u64::MAX / 2 }
}
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
would do the trick, but I am wondering if there's a better way to do this.
Manual for mach_absolute_time
(https://developer.apple.com/documentation/kernel/1462446-mach_absolute_time) also suggests using clock_gettime_nsec_np(CLOCK_UPTIME_RAW)
instead, so we can perhaps switch to that while we are at it.