From a5186a9d8b3cd236fb3535eb419f88436d264f42 Mon Sep 17 00:00:00 2001 From: Mark Leyva Date: Mon, 15 Jul 2024 05:10:31 -0700 Subject: [PATCH] Use monotonic timestamp to calculate timeouts refs #23826 (#23834) Related to #23826. This address issues raised [here](https://github.com/nim-lang/Nim/pull/23826#issuecomment-2226877361) by using a monotonic timestamp to calculate timeouts and increasing the max sleep time to 50ms. --- lib/pure/osproc.nim | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index ee824db9beb9..2deb9fcaa130 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -1353,7 +1353,8 @@ elif not defined(useNimRtl): result = exitStatusLikeShell(p.exitStatus) else: - import std/times + import std/times except getTime + import std/monotimes proc waitForExit(p: Process, timeout: int = -1): int = if p.exitFlag: @@ -1369,10 +1370,10 @@ elif not defined(useNimRtl): p.exitFlag = true p.exitStatus = status else: - # Max 1ms delay - const maxWait = initDuration(milliseconds = 1) + # Max 50ms delay + const maxWait = initDuration(milliseconds = 50) let wait = initDuration(milliseconds = timeout) - let deadline = getTime() + wait + let deadline = getMonoTime() + wait # starting 50μs delay var delay = initDuration(microseconds = 50) @@ -1387,7 +1388,7 @@ elif not defined(useNimRtl): raiseOsError(osLastError()) else: # Continue waiting if needed - if getTime() >= deadline: + if getMonoTime() >= deadline: # Previous version of `waitForExit` # foricibly killed the process. # We keep this so we don't break programs @@ -1395,14 +1396,19 @@ elif not defined(useNimRtl): if posix.kill(p.id, SIGKILL) < 0: raiseOSError(osLastError()) else: - let newWait = getTime() + delay + const max = 1_000_000_000 + let + newWait = getMonoTime() + delay + ticks = newWait.ticks() + ns = ticks mod max + secs = ticks div max var waitSpec: TimeSpec unused: Timespec - waitSpec.tv_sec = posix.Time(newWait.toUnix()) - waitSpec.tv_nsec = newWait.nanosecond.clong - discard posix.clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, waitSpec, unused) - let remaining = deadline - getTime() + waitSpec.tv_sec = posix.Time(secs) + waitSpec.tv_nsec = ns + discard posix.clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, waitSpec, unused) + let remaining = deadline - getMonoTime() delay = min([delay * 2, remaining, maxWait]) result = exitStatusLikeShell(p.exitStatus)