authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-22 07:26:51+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-04-22 07:26:51+02:00
log5da0e0355399acdb0896ad4ac691ecfc9d32222f
tree07d42872f99a212b1afc76a7935ddf17780cecb7
parent5c501e8dad51f421784bb6fc9671b01016e5ee7f
parent50ec55faaf4b218c4ded8a73864bbd0c85571e23
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11480 from rabingaire/fix-child-process-hang-on-macos

Fix child process spawn on macos hangs with stdin, stdout behavior set to pipe

1 files changed, 53 insertions(+), 5 deletions(-)

lib/std/child_process.zig+53-5
...@@ -593,9 +593,9 @@ pub const ChildProcess = struct {...@@ -593,9 +593,9 @@ pub const ChildProcess = struct {
593 var actions = try os.posix_spawn.Actions.init();593 var actions = try os.posix_spawn.Actions.init();
594 defer actions.deinit();594 defer actions.deinit();
595595
596 try setUpChildIoPosixSpawn(self.stdin_behavior, &actions, stdin_pipe[0], os.STDIN_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[1], os.STDOUT_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[1], os.STDERR_FILENO, dev_null_fd);598 try setUpChildIoPosixSpawn(self.stderr_behavior, &actions, stderr_pipe, os.STDERR_FILENO, dev_null_fd);
599599
600 if (self.cwd_dir) |cwd| {600 if (self.cwd_dir) |cwd| {
601 try actions.fchdir(cwd.fd);601 try actions.fchdir(cwd.fd);
...@@ -650,12 +650,16 @@ pub const ChildProcess = struct {...@@ -650,12 +650,16 @@ pub const ChildProcess = struct {
650 fn setUpChildIoPosixSpawn(650 fn setUpChildIoPosixSpawn(
651 stdio: StdIo,651 stdio: StdIo,
652 actions: *os.posix_spawn.Actions,652 actions: *os.posix_spawn.Actions,
653 pipe_fd: i32,653 pipe_fd: [2]i32,
654 std_fileno: i32,654 std_fileno: i32,
655 dev_null_fd: i32,655 dev_null_fd: i32,
656 ) !void {656 ) !void {
657 switch (stdio) {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 .Close => try actions.close(std_fileno),663 .Close => try actions.close(std_fileno),
660 .Inherit => {},664 .Inherit => {},
661 .Ignore => try actions.dup2(dev_null_fd, std_fileno),665 .Ignore => try actions.dup2(dev_null_fd, std_fileno),
...@@ -1375,3 +1379,47 @@ test "build and call child_process" {...@@ -1375,3 +1379,47 @@ test "build and call child_process" {
1375 const ret_val = try child_proc.spawnAndWait();1379 const ret_val = try child_proc.spawnAndWait();
1376 try testing.expectEqual(ret_val, .{ .Exited = 0 });1380 try testing.expectEqual(ret_val, .{ .Exited = 0 });
1377}1381}
1382
1383test "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}