| ... | @@ -197,6 +197,32 @@ pub const ChildProcess = struct { | ... | @@ -197,6 +197,32 @@ pub const ChildProcess = struct { |
| 197 | stderr: []u8, | 197 | stderr: []u8, |
| 198 | }; | 198 | }; |
| 199 | | 199 | |
| | 200 | /// Collect the output from the process's stdout and stderr. Will return once all output |
| | 201 | /// has been collected. This does not mean that the process has ended. `wait` should still |
| | 202 | /// be called to wait for and clean up the process. |
| | 203 | /// |
| | 204 | /// The process must be started with stdout_behavior and stderr_behavior == .Pipe |
| | 205 | pub fn collectOutput( |
| | 206 | child: ChildProcess, |
| | 207 | stdout: *std.ArrayList(u8), |
| | 208 | stderr: *std.ArrayList(u8), |
| | 209 | max_output_bytes: usize, |
| | 210 | ) !void { |
| | 211 | debug.assert(child.stdout_behavior == .Pipe); |
| | 212 | debug.assert(child.stderr_behavior == .Pipe); |
| | 213 | if (builtin.os.tag == .haiku) { |
| | 214 | const stdout_in = child.stdout.?.reader(); |
| | 215 | const stderr_in = child.stderr.?.reader(); |
| | 216 | |
| | 217 | try stdout_in.readAllArrayList(stdout, max_output_bytes); |
| | 218 | try stderr_in.readAllArrayList(stderr, max_output_bytes); |
| | 219 | } else if (builtin.os.tag == .windows) { |
| | 220 | try collectOutputWindows(child, stdout, stderr, max_output_bytes); |
| | 221 | } else { |
| | 222 | try collectOutputPosix(child, stdout, stderr, max_output_bytes); |
| | 223 | } |
| | 224 | } |
| | 225 | |
| 200 | fn collectOutputPosix( | 226 | fn collectOutputPosix( |
| 201 | child: ChildProcess, | 227 | child: ChildProcess, |
| 202 | stdout: *std.ArrayList(u8), | 228 | stdout: *std.ArrayList(u8), |
| ... | @@ -297,8 +323,12 @@ pub const ChildProcess = struct { | ... | @@ -297,8 +323,12 @@ pub const ChildProcess = struct { |
| 297 | } | 323 | } |
| 298 | } | 324 | } |
| 299 | | 325 | |
| 300 | fn collectOutputWindows(child: ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void { | 326 | fn collectOutputWindows(child: ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize) !void { |
| 301 | const bump_amt = 512; | 327 | const bump_amt = 512; |
| | 328 | const outs = [_]*std.ArrayList(u8){ |
| | 329 | stdout, |
| | 330 | stderr, |
| | 331 | }; |
| 302 | const handles = [_]windows.HANDLE{ | 332 | const handles = [_]windows.HANDLE{ |
| 303 | child.stdout.?.handle, | 333 | child.stdout.?.handle, |
| 304 | child.stderr.?.handle, | 334 | child.stderr.?.handle, |
| ... | @@ -391,24 +421,6 @@ pub const ChildProcess = struct { | ... | @@ -391,24 +421,6 @@ pub const ChildProcess = struct { |
| 391 | child.env_map = args.env_map; | 421 | child.env_map = args.env_map; |
| 392 | child.expand_arg0 = args.expand_arg0; | 422 | child.expand_arg0 = args.expand_arg0; |
| 393 | | 423 | |
| 394 | try child.spawn(); | | |
| 395 | | | |
| 396 | if (builtin.os.tag == .haiku) { | | |
| 397 | const stdout_in = child.stdout.?.reader(); | | |
| 398 | const stderr_in = child.stderr.?.reader(); | | |
| 399 | | | |
| 400 | const stdout = try stdout_in.readAllAlloc(args.allocator, args.max_output_bytes); | | |
| 401 | errdefer args.allocator.free(stdout); | | |
| 402 | const stderr = try stderr_in.readAllAlloc(args.allocator, args.max_output_bytes); | | |
| 403 | errdefer args.allocator.free(stderr); | | |
| 404 | | | |
| 405 | return ExecResult{ | | |
| 406 | .term = try child.wait(), | | |
| 407 | .stdout = stdout, | | |
| 408 | .stderr = stderr, | | |
| 409 | }; | | |
| 410 | } | | |
| 411 | | | |
| 412 | var stdout = std.ArrayList(u8).init(args.allocator); | 424 | var stdout = std.ArrayList(u8).init(args.allocator); |
| 413 | var stderr = std.ArrayList(u8).init(args.allocator); | 425 | var stderr = std.ArrayList(u8).init(args.allocator); |
| 414 | errdefer { | 426 | errdefer { |
| ... | @@ -416,11 +428,8 @@ pub const ChildProcess = struct { | ... | @@ -416,11 +428,8 @@ pub const ChildProcess = struct { |
| 416 | stderr.deinit(); | 428 | stderr.deinit(); |
| 417 | } | 429 | } |
| 418 | | 430 | |
| 419 | if (builtin.os.tag == .windows) { | 431 | try child.spawn(); |
| 420 | try collectOutputWindows(child, [_]*std.ArrayList(u8){ &stdout, &stderr }, args.max_output_bytes); | 432 | try child.collectOutput(&stdout, &stderr, args.max_output_bytes); |
| 421 | } else { | | |
| 422 | try collectOutputPosix(child, &stdout, &stderr, args.max_output_bytes); | | |
| 423 | } | | |
| 424 | | 433 | |
| 425 | return ExecResult{ | 434 | return ExecResult{ |
| 426 | .term = try child.wait(), | 435 | .term = try child.wait(), |