Skip to content

Commit

Permalink
std.process.Child: implement maxrss on Darwin
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tjog authored and kubkon committed Mar 25, 2023
1 parent f99b753 commit f6a2b72
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
28 changes: 20 additions & 8 deletions lib/std/child_process.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 => {},
};
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion lib/std/process.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down

0 comments on commit f6a2b72

Please sign in to comment.