From 25a08966c327a5e6094e72b951fd1147da39d01d Mon Sep 17 00:00:00 2001 From: tjog <28024277+tjog@users.noreply.github.com> Date: Thu, 23 Mar 2023 02:21:15 +0800 Subject: [PATCH] std.process.Child: implement maxrss on Darwin Notably the Darwin (XNU) kernel the maxrss field is number of bytes and not kilobytes (kibibytes) like other platforms (e.g. Linux, BSD). watchOS and tvOS are not supported because they do not have the ability to spawn a child process. iOS is enabled but due to OS sandboxing it should fail with a permission error. --- lib/std/child_process.zig | 28 ++++++++++++++++++++-------- lib/std/process.zig | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index ca447b068df7..bd67d344c70b 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -17,7 +17,6 @@ const Os = std.builtin.Os; const TailQueue = std.TailQueue; const maxInt = std.math.maxInt; const assert = std.debug.assert; -const is_darwin = builtin.target.isDarwin(); pub const ChildProcess = struct { pub const Id = switch (builtin.os.tag) { @@ -77,7 +76,7 @@ pub const ChildProcess = struct { /// requested statistics may or may not be available. If they are /// available, then the `resource_usage_statistics` field will be populated /// after calling `wait`. - /// On Linux, this obtains rusage statistics from wait4(). + /// On Linux and Darwin, this obtains rusage statistics from wait4(). request_resource_usage_statistics: bool = false, /// This is available after calling wait if @@ -106,12 +105,20 @@ pub const ChildProcess = struct { return null; } }, + .macos, .ios => { + if (rus.rusage) |ru| { + // Darwin oddly reports in bytes instead of kilobytes. + return @intCast(usize, ru.maxrss); + } else { + return null; + } + }, else => return null, } } const rusage_init = switch (builtin.os.tag) { - .linux => @as(?std.os.rusage, null), + .linux, .macos, .ios => @as(?std.os.rusage, null), .windows => @as(?windows.VM_COUNTERS, null), else => {}, }; @@ -385,11 +392,16 @@ pub const ChildProcess = struct { fn waitUnwrapped(self: *ChildProcess) !void { const res: os.WaitPidResult = res: { - if (builtin.os.tag == .linux and self.request_resource_usage_statistics) { - var ru: std.os.rusage = undefined; - const res = os.wait4(self.id, 0, &ru); - self.resource_usage_statistics.rusage = ru; - break :res res; + if (self.request_resource_usage_statistics) { + switch (builtin.os.tag) { + .linux, .macos, .ios => { + var ru: std.os.rusage = undefined; + const res = os.wait4(self.id, 0, &ru); + self.resource_usage_statistics.rusage = ru; + break :res res; + }, + else => {}, + } } break :res os.waitpid(self.id, 0); diff --git a/lib/std/process.zig b/lib/std/process.zig index d06a012af2a8..f870b857746d 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1093,7 +1093,7 @@ pub const can_execv = switch (builtin.os.tag) { /// Tells whether spawning child processes is supported (e.g. via ChildProcess) pub const can_spawn = switch (builtin.os.tag) { - .wasi => false, + .wasi, .watchos, .tvos => false, else => true, };