From 98bc2b73bf6974a782e2df0ea71b409a68e030fd Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 4 May 2019 09:03:01 +0200 Subject: [PATCH] Implement failsafe logic for posixSleep Now we'll sleep for the specified amount of time even though the number of seconds doesn't fit in a `isize` field. --- std/os/time.zig | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/std/os/time.zig b/std/os/time.zig index fb39fda1d..99c8b5992 100644 --- a/std/os/time.zig +++ b/std/os/time.zig @@ -3,6 +3,7 @@ const builtin = @import("builtin"); const Os = builtin.Os; const debug = std.debug; const testing = std.testing; +const math = std.math; const windows = std.os.windows; const linux = std.os.linux; @@ -30,16 +31,26 @@ pub fn sleep(nanoseconds: u64) void { } pub fn posixSleep(seconds: u63, nanoseconds: u63) void { - var req = posix.timespec{ - .tv_sec = @intCast(isize, seconds), - .tv_nsec = @intCast(isize, nanoseconds), - }; + var req: posix.timespec = undefined; var rem: posix.timespec = undefined; + + var req_sec = seconds; + var req_nsec = nanoseconds; + while (true) { + req.tv_sec = math.min(math.maxInt(isize), req_sec); + req.tv_nsec = @intCast(isize, req_nsec); + + req_sec -= @intCast(u63, req.tv_sec); + req_nsec = 0; + const ret_val = posix.nanosleep(&req, &rem); const err = posix.getErrno(ret_val); - if (err == 0) return; switch (err) { + 0 => { + // If there's still time to wait keep running the loop + if (req_sec == 0 and req_nsec == 0) return; + }, posix.EFAULT => unreachable, posix.EINVAL => { // Sometimes Darwin returns EINVAL for no reason. @@ -47,7 +58,8 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void { return; }, posix.EINTR => { - req = rem; + req_sec += @intCast(u63, rem.tv_sec); + req_nsec = @intCast(u63, rem.tv_nsec); continue; }, else => return,