authorgravatar for 28024277+tjog@users.noreply.github.comtjog <28024277+tjog@users.noreply.github.com> 2023-03-23 02:21:15+08:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-25 03:20:50+01:00
logf6a2b72ba8b6ab8f8dbef223788c6458af3d4da0
tree0728917fa73f5a86d9428f8f2e59957dd9237425
parentf99b75360db55413f4accf43a6f4161b14a5de9f

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.

2 files changed, 21 insertions(+), 9 deletions(-)

lib/std/child_process.zig+20-8
...@@ -17,7 +17,6 @@ const Os = std.builtin.Os;...@@ -17,7 +17,6 @@ const Os = std.builtin.Os;
17const TailQueue = std.TailQueue;17const TailQueue = std.TailQueue;
18const maxInt = std.math.maxInt;18const maxInt = std.math.maxInt;
19const assert = std.debug.assert;19const assert = std.debug.assert;
20const is_darwin = builtin.target.isDarwin();
2120
22pub const ChildProcess = struct {21pub const ChildProcess = struct {
23 pub const Id = switch (builtin.os.tag) {22 pub const Id = switch (builtin.os.tag) {
...@@ -77,7 +76,7 @@ pub const ChildProcess = struct {...@@ -77,7 +76,7 @@ pub const ChildProcess = struct {
77 /// requested statistics may or may not be available. If they are76 /// requested statistics may or may not be available. If they are
78 /// available, then the `resource_usage_statistics` field will be populated77 /// available, then the `resource_usage_statistics` field will be populated
79 /// after calling `wait`.78 /// after calling `wait`.
80 /// On Linux, this obtains rusage statistics from wait4().79 /// On Linux and Darwin, this obtains rusage statistics from wait4().
81 request_resource_usage_statistics: bool = false,80 request_resource_usage_statistics: bool = false,
8281
83 /// This is available after calling wait if82 /// This is available after calling wait if
...@@ -106,12 +105,20 @@ pub const ChildProcess = struct {...@@ -106,12 +105,20 @@ pub const ChildProcess = struct {
106 return null;105 return null;
107 }106 }
108 },107 },
108 .macos, .ios => {
109 if (rus.rusage) |ru| {
110 // Darwin oddly reports in bytes instead of kilobytes.
111 return @intCast(usize, ru.maxrss);
112 } else {
113 return null;
114 }
115 },
109 else => return null,116 else => return null,
110 }117 }
111 }118 }
112119
113 const rusage_init = switch (builtin.os.tag) {120 const rusage_init = switch (builtin.os.tag) {
114 .linux => @as(?std.os.rusage, null),121 .linux, .macos, .ios => @as(?std.os.rusage, null),
115 .windows => @as(?windows.VM_COUNTERS, null),122 .windows => @as(?windows.VM_COUNTERS, null),
116 else => {},123 else => {},
117 };124 };
...@@ -385,11 +392,16 @@ pub const ChildProcess = struct {...@@ -385,11 +392,16 @@ pub const ChildProcess = struct {
385392
386 fn waitUnwrapped(self: *ChildProcess) !void {393 fn waitUnwrapped(self: *ChildProcess) !void {
387 const res: os.WaitPidResult = res: {394 const res: os.WaitPidResult = res: {
388 if (builtin.os.tag == .linux and self.request_resource_usage_statistics) {395 if (self.request_resource_usage_statistics) {
389 var ru: std.os.rusage = undefined;396 switch (builtin.os.tag) {
390 const res = os.wait4(self.id, 0, &ru);397 .linux, .macos, .ios => {
391 self.resource_usage_statistics.rusage = ru;398 var ru: std.os.rusage = undefined;
392 break :res res;399 const res = os.wait4(self.id, 0, &ru);
400 self.resource_usage_statistics.rusage = ru;
401 break :res res;
402 },
403 else => {},
404 }
393 }405 }
394406
395 break :res os.waitpid(self.id, 0);407 break :res os.waitpid(self.id, 0);
lib/std/process.zig+1-1
...@@ -1093,7 +1093,7 @@ pub const can_execv = switch (builtin.os.tag) {...@@ -1093,7 +1093,7 @@ pub const can_execv = switch (builtin.os.tag) {
10931093
1094/// Tells whether spawning child processes is supported (e.g. via ChildProcess)1094/// Tells whether spawning child processes is supported (e.g. via ChildProcess)
1095pub const can_spawn = switch (builtin.os.tag) {1095pub const can_spawn = switch (builtin.os.tag) {
1096 .wasi => false,1096 .wasi, .watchos, .tvos => false,
1097 else => true,1097 else => true,
1098};1098};
10991099