Skip to content

Subtracting Duration from Instant on Mac is panic-prone #100141

Open
@matklad

Description

@matklad

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-timeArea: TimeC-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions