From 2737dce84f99a05af51b66fc12794b43dc10fa41 Mon Sep 17 00:00:00 2001 From: Komari Spaghetti Date: Tue, 21 Feb 2023 18:26:55 +0100 Subject: [PATCH] Introduce ChildProcess.collectOutput (#12295) All the code for this function already exists, but only ChildProcess.exec was allowed to use the code. --- lib/std/child_process.zig | 57 ++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 07dd1f27f5..c3bd53b880 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -197,6 +197,32 @@ pub const ChildProcess = struct { stderr: []u8, }; + /// Collect the output from the process's stdout and stderr. Will return once all output + /// has been collected. This does not mean that the process has ended. `wait` should still + /// be called to wait for and clean up the process. + /// + /// The process must be started with stdout_behavior and stderr_behavior == .Pipe + pub fn collectOutput( + child: ChildProcess, + stdout: *std.ArrayList(u8), + stderr: *std.ArrayList(u8), + max_output_bytes: usize, + ) !void { + debug.assert(child.stdout_behavior == .Pipe); + debug.assert(child.stderr_behavior == .Pipe); + if (builtin.os.tag == .haiku) { + const stdout_in = child.stdout.?.reader(); + const stderr_in = child.stderr.?.reader(); + + try stdout_in.readAllArrayList(stdout, max_output_bytes); + try stderr_in.readAllArrayList(stderr, max_output_bytes); + } else if (builtin.os.tag == .windows) { + try collectOutputWindows(child, stdout, stderr, max_output_bytes); + } else { + try collectOutputPosix(child, stdout, stderr, max_output_bytes); + } + } + fn collectOutputPosix( child: ChildProcess, stdout: *std.ArrayList(u8), @@ -297,8 +323,12 @@ pub const ChildProcess = struct { } } - fn collectOutputWindows(child: ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void { + fn collectOutputWindows(child: ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void { const bump_amt = 512; + const outs = [_]*std.ArrayList(u8){ + stdout, + stderr, + }; const handles = [_]windows.HANDLE{ child.stdout.?.handle, child.stderr.?.handle, @@ -391,24 +421,6 @@ pub const ChildProcess = struct { child.env_map = args.env_map; child.expand_arg0 = args.expand_arg0; - try child.spawn(); - - if (builtin.os.tag == .haiku) { - const stdout_in = child.stdout.?.reader(); - const stderr_in = child.stderr.?.reader(); - - const stdout = try stdout_in.readAllAlloc(args.allocator, args.max_output_bytes); - errdefer args.allocator.free(stdout); - const stderr = try stderr_in.readAllAlloc(args.allocator, args.max_output_bytes); - errdefer args.allocator.free(stderr); - - return ExecResult{ - .term = try child.wait(), - .stdout = stdout, - .stderr = stderr, - }; - } - var stdout = std.ArrayList(u8).init(args.allocator); var stderr = std.ArrayList(u8).init(args.allocator); errdefer { @@ -416,11 +428,8 @@ pub const ChildProcess = struct { stderr.deinit(); } - if (builtin.os.tag == .windows) { - try collectOutputWindows(child, [_]*std.ArrayList(u8){ &stdout, &stderr }, args.max_output_bytes); - } else { - try collectOutputPosix(child, &stdout, &stderr, args.max_output_bytes); - } + try child.spawn(); + try child.collectOutput(&stdout, &stderr, args.max_output_bytes); return ExecResult{ .term = try child.wait(),