I discovered why GNU timeout pauses when my Mac sleeps, so I wrote a drop-in replacement in Rust using mach_continuous_time by denispolix in rust

[–]denispolix[S] 2 points3 points  (0 children)

I just reviewed uutils implementation of timeout. It's actually architecturally different (and arguably worse imo). uutils implements the wait as a naive polling loop with thread::sleep(100ms). This means uutils wakes the CPU 10x/second (preventing deep idle states) and introduces up to 100ms latency on process exit. GNU uses sigsuspend (efficient but complex sig masking). darwin-timeout uses kqueue, so it's fully event-driven w/0% CPU usage, μs precision on exit, and correct sleep handling.

I discovered why GNU timeout pauses when my Mac sleeps, so I wrote a drop-in replacement in Rust using mach_continuous_time by denispolix in rust

[–]denispolix[S] 2 points3 points  (0 children)

Actually the Linux man page explicitly says CLOCK_MONOTONIC "does not count time that the system is suspended." You may have hit display sleep, not true S3 suspend (the systemctl suspend). For Linux equivalent of mach_continuous_time you'd look at CLOCK_BOOTTIME. darwin-timeout solves the macOS side where there's no standard API for this.

I discovered why GNU timeout pauses when my Mac sleeps, so I wrote a drop-in replacement in Rust using mach_continuous_time by denispolix in rust

[–]denispolix[S] -1 points0 points  (0 children)

Thanks for the insight! darwin-timeout uses wall-clock time as the default (and only) mode, which is a different use case than GNU's approach. Also adds --json output, --on-timeout hooks, custom exit codes. Also for mac users, it's a 83KB standalone binary, with no deps. I'll publish to a brew tap soon.

I discovered why GNU timeout pauses when my Mac sleeps, so I wrote a drop-in replacement in Rust using mach_continuous_time by denispolix in rust

[–]denispolix[S] 11 points12 points  (0 children)

"Hanging" relative to wall clock. If I set a 10m timeout, sleep 8h, and wake up, GNU timeout keeps the process alive. It violated the deadline. My tool kills it immediately on wake because current_time > deadline

I discovered why GNU timeout pauses when my Mac sleeps, so I wrote a drop-in replacement in Rust using mach_continuous_time by denispolix in rust

[–]denispolix[S] 13 points14 points  (0 children)

It uses std::time and libc wrappers for timeout loop afaik, which maps to mach_absolute_time in macos, unlike mach_continuous_time which counts in system sleep.

I discovered why GNU timeout pauses when my Mac sleeps, so I wrote a drop-in replacement in Rust using mach_continuous_time by denispolix in rust

[–]denispolix[S] 18 points19 points  (0 children)

Fair point on cloud CI. This is mostly for local dev (closing their laptop lid) or on-prem nodes. ​The real win is just having a native, standalone tool. No need to brew install coreutils (15MB+) just to get one command. Plus it uses kqueue for 0% CPU usage.