| ... | ... | @@ -593,9 +593,9 @@ pub const ChildProcess = struct { |
| 593 | 593 | var actions = try os.posix_spawn.Actions.init(); |
| 594 | 594 | defer actions.deinit(); |
| 595 | 595 | |
| 596 | | try setUpChildIoPosixSpawn(self.stdin_behavior, &actions, stdin_pipe[0], os.STDIN_FILENO, dev_null_fd); |
| 597 | | try setUpChildIoPosixSpawn(self.stdout_behavior, &actions, stdout_pipe[1], os.STDOUT_FILENO, dev_null_fd); |
| 598 | | try setUpChildIoPosixSpawn(self.stderr_behavior, &actions, stderr_pipe[1], os.STDERR_FILENO, dev_null_fd); |
| 596 | try setUpChildIoPosixSpawn(self.stdin_behavior, &actions, stdin_pipe, os.STDIN_FILENO, dev_null_fd); |
| 597 | try setUpChildIoPosixSpawn(self.stdout_behavior, &actions, stdout_pipe, os.STDOUT_FILENO, dev_null_fd); |
| 598 | try setUpChildIoPosixSpawn(self.stderr_behavior, &actions, stderr_pipe, os.STDERR_FILENO, dev_null_fd); |
| 599 | 599 | |
| 600 | 600 | if (self.cwd_dir) |cwd| { |
| 601 | 601 | try actions.fchdir(cwd.fd); |
| ... | ... | @@ -650,12 +650,16 @@ pub const ChildProcess = struct { |
| 650 | 650 | fn setUpChildIoPosixSpawn( |
| 651 | 651 | stdio: StdIo, |
| 652 | 652 | actions: *os.posix_spawn.Actions, |
| 653 | | pipe_fd: i32, |
| 653 | pipe_fd: [2]i32, |
| 654 | 654 | std_fileno: i32, |
| 655 | 655 | dev_null_fd: i32, |
| 656 | 656 | ) !void { |
| 657 | 657 | switch (stdio) { |
| 658 | | .Pipe => try actions.dup2(pipe_fd, std_fileno), |
| 658 | .Pipe => { |
| 659 | const idx: usize = if (std_fileno == 0) 0 else 1; |
| 660 | try actions.dup2(pipe_fd[idx], std_fileno); |
| 661 | try actions.close(pipe_fd[1 - idx]); |
| 662 | }, |
| 659 | 663 | .Close => try actions.close(std_fileno), |
| 660 | 664 | .Inherit => {}, |
| 661 | 665 | .Ignore => try actions.dup2(dev_null_fd, std_fileno), |
| ... | ... | @@ -1375,3 +1379,47 @@ test "build and call child_process" { |
| 1375 | 1379 | const ret_val = try child_proc.spawnAndWait(); |
| 1376 | 1380 | try testing.expectEqual(ret_val, .{ .Exited = 0 }); |
| 1377 | 1381 | } |
| 1382 | |
| 1383 | test "creating a child process with stdin and stdout behavior set to StdIo.Pipe" { |
| 1384 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 1385 | const testing = std.testing; |
| 1386 | const allocator = testing.allocator; |
| 1387 | |
| 1388 | var child_process = try std.ChildProcess.init( |
| 1389 | &[_][]const u8{ testing.zig_exe_path, "fmt", "--stdin" }, |
| 1390 | allocator, |
| 1391 | ); |
| 1392 | defer child_process.deinit(); |
| 1393 | child_process.stdin_behavior = .Pipe; |
| 1394 | child_process.stdout_behavior = .Pipe; |
| 1395 | |
| 1396 | try child_process.spawn(); |
| 1397 | |
| 1398 | const input_program = |
| 1399 | \\ const std = @import("std"); |
| 1400 | \\ pub fn main() void { |
| 1401 | \\ std.debug.print("Hello World", .{}); |
| 1402 | \\ } |
| 1403 | ; |
| 1404 | |
| 1405 | try child_process.stdin.?.writer().writeAll(input_program); |
| 1406 | child_process.stdin.?.close(); |
| 1407 | child_process.stdin = null; |
| 1408 | |
| 1409 | const out_bytes = try child_process.stdout.?.reader().readAllAlloc(allocator, std.math.maxInt(usize)); |
| 1410 | defer allocator.free(out_bytes); |
| 1411 | |
| 1412 | switch (try child_process.wait()) { |
| 1413 | .Exited => |code| if (code == 0) { |
| 1414 | const expected_program = |
| 1415 | \\const std = @import("std"); |
| 1416 | \\pub fn main() void { |
| 1417 | \\ std.debug.print("Hello World", .{}); |
| 1418 | \\} |
| 1419 | \\ |
| 1420 | ; |
| 1421 | try testing.expectEqualStrings(expected_program, out_bytes); |
| 1422 | }, |
| 1423 | else => unreachable, |
| 1424 | } |
| 1425 | } |