Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use monotonic timestamp to calculate timeouts refs #23826 #23834

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions lib/pure/osproc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)

Expand All @@ -1387,22 +1388,27 @@ 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
# that depend on this behavior
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)
Expand Down
Loading