From a0a2ce92ca129d28e22c63f7bace1672c43776b5 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Fri, 29 Apr 2022 17:07:51 +0200 Subject: [PATCH] std: Do not allocate the result for ChildProcess.init Instead, just return ChildProcess directly. This structure does not require a stable address, so we can put it on the stack just fine. If someone wants it on the heap they should do. const proc = try allocator.create(ChildProcess); proc.* = ChildProcess.init(args, allocator); --- lib/std/build.zig | 8 ++------ lib/std/build/RunStep.zig | 4 +--- lib/std/child_process.zig | 26 +++++++------------------- lib/std/testing.zig | 5 +++-- src/Compilation.zig | 4 +--- src/link/Coff.zig | 4 +--- src/link/Elf.zig | 4 +--- src/link/Wasm.zig | 4 +--- src/main.zig | 8 ++------ src/mingw.zig | 4 +--- test/tests.zig | 4 +--- 11 files changed, 21 insertions(+), 54 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 453f20c333..38744cea1e 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -971,9 +971,7 @@ pub const Builder = struct { if (!std.process.can_spawn) return error.ExecNotSupported; - const child = std.ChildProcess.init(argv, self.allocator) catch unreachable; - defer child.deinit(); - + var child = std.ChildProcess.init(argv, self.allocator); child.cwd = cwd; child.env_map = env_map; @@ -1187,9 +1185,7 @@ pub const Builder = struct { return error.ExecNotSupported; const max_output_size = 400 * 1024; - const child = try std.ChildProcess.init(argv, self.allocator); - defer child.deinit(); - + var child = std.ChildProcess.init(argv, self.allocator); child.stdin_behavior = .Ignore; child.stdout_behavior = .Pipe; child.stderr_behavior = stderr_behavior; diff --git a/lib/std/build/RunStep.zig b/lib/std/build/RunStep.zig index e8544921d9..e00fe3deb6 100644 --- a/lib/std/build/RunStep.zig +++ b/lib/std/build/RunStep.zig @@ -184,9 +184,7 @@ fn make(step: *Step) !void { return ExecError.ExecNotSupported; } - const child = std.ChildProcess.init(argv, self.builder.allocator) catch unreachable; - defer child.deinit(); - + var child = std.ChildProcess.init(argv, self.builder.allocator); child.cwd = cwd; child.env_map = self.env_map orelse self.builder.env_map; diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index f2b978ba9f..5f01ed01dd 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -98,10 +98,8 @@ pub const ChildProcess = struct { }; /// First argument in argv is the executable. - /// On success must call deinit. - pub fn init(argv: []const []const u8, allocator: mem.Allocator) !*ChildProcess { - const child = try allocator.create(ChildProcess); - child.* = ChildProcess{ + pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess { + return .{ .allocator = allocator, .argv = argv, .pid = undefined, @@ -121,8 +119,6 @@ pub const ChildProcess = struct { .stderr_behavior = StdIo.Inherit, .expand_arg0 = .no_expand, }; - errdefer allocator.destroy(child); - return child; } pub fn setUserName(self: *ChildProcess, name: []const u8) !void { @@ -199,7 +195,7 @@ pub const ChildProcess = struct { }; fn collectOutputPosix( - child: *const ChildProcess, + child: ChildProcess, stdout: *std.ArrayList(u8), stderr: *std.ArrayList(u8), max_output_bytes: usize, @@ -298,7 +294,7 @@ pub const ChildProcess = struct { } } - fn collectOutputWindows(child: *const ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void { + fn collectOutputWindows(child: ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void { const bump_amt = 512; const handles = [_]windows.HANDLE{ child.stdout.?.handle, @@ -383,9 +379,7 @@ pub const ChildProcess = struct { max_output_bytes: usize = 50 * 1024, expand_arg0: Arg0Expand = .no_expand, }) !ExecResult { - const child = try ChildProcess.init(args.argv, args.allocator); - defer child.deinit(); - + var child = ChildProcess.init(args.argv, args.allocator); child.stdin_behavior = .Ignore; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe; @@ -452,10 +446,6 @@ pub const ChildProcess = struct { return self.term.?; } - pub fn deinit(self: *ChildProcess) void { - self.allocator.destroy(self); - } - fn waitUnwrappedWindows(self: *ChildProcess) !void { const result = windows.WaitForSingleObjectEx(self.handle, windows.INFINITE, false); @@ -1374,8 +1364,7 @@ test "build and call child_process" { // spawn compiled file as child_process with argument 'hello world' + expect success const args = [_][]const u8{ child_path, "hello world" }; - var child_proc = try ChildProcess.init(&args, allocator); - defer child_proc.deinit(); + var child_proc = ChildProcess.init(&args, allocator); const ret_val = try child_proc.spawnAndWait(); try testing.expectEqual(ret_val, .{ .Exited = 0 }); } @@ -1385,11 +1374,10 @@ test "creating a child process with stdin and stdout behavior set to StdIo.Pipe" const testing = std.testing; const allocator = testing.allocator; - var child_process = try std.ChildProcess.init( + var child_process = std.ChildProcess.init( &[_][]const u8{ testing.zig_exe_path, "fmt", "--stdin" }, allocator, ); - defer child_process.deinit(); child_process.stdin_behavior = .Pipe; child_process.stdout_behavior = .Pipe; diff --git a/lib/std/testing.zig b/lib/std/testing.zig index cfdf300c04..174e898bca 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -442,10 +442,11 @@ pub fn buildExe(zigexec: []const u8, zigfile: []const u8, binfile: []const u8) ! const flag_emit = "-femit-bin="; const cmd_emit = try std.mem.concat(allocator, u8, &[_][]const u8{ flag_emit, binfile }); defer allocator.free(cmd_emit); + const args = [_][]const u8{ zigexec, "build-exe", zigfile, cmd_emit }; - var procCompileChild = try std.ChildProcess.init(&args, allocator); - defer procCompileChild.deinit(); + var procCompileChild = std.ChildProcess.init(&args, allocator); try procCompileChild.spawn(); + const ret_val = try procCompileChild.wait(); try expectEqual(ret_val, .{ .Exited = 0 }); } diff --git a/src/Compilation.zig b/src/Compilation.zig index b0c8f5f475..2ad8a9e030 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3611,9 +3611,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P } if (std.process.can_spawn) { - const child = try std.ChildProcess.init(argv.items, arena); - defer child.deinit(); - + var child = std.ChildProcess.init(argv.items, arena); if (comp.clang_passthrough_mode) { child.stdin_behavior = .Inherit; child.stdout_behavior = .Inherit; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 246918515d..178a6ab6b4 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1390,9 +1390,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! // If possible, we run LLD as a child process because it does not always // behave properly as a library, unfortunately. // https://github.com/ziglang/zig/issues/3825 - const child = try std.ChildProcess.init(argv.items, arena); - defer child.deinit(); - + var child = std.ChildProcess.init(argv.items, arena); if (comp.clang_passthrough_mode) { child.stdin_behavior = .Inherit; child.stdout_behavior = .Inherit; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 144ac24b9b..11a701fcf9 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1754,9 +1754,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // If possible, we run LLD as a child process because it does not always // behave properly as a library, unfortunately. // https://github.com/ziglang/zig/issues/3825 - const child = try std.ChildProcess.init(argv.items, arena); - defer child.deinit(); - + var child = std.ChildProcess.init(argv.items, arena); if (comp.clang_passthrough_mode) { child.stdin_behavior = .Inherit; child.stdout_behavior = .Inherit; diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 3c53e91587..4e898cee07 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2405,9 +2405,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // If possible, we run LLD as a child process because it does not always // behave properly as a library, unfortunately. // https://github.com/ziglang/zig/issues/3825 - const child = try std.ChildProcess.init(argv.items, arena); - defer child.deinit(); - + var child = std.ChildProcess.init(argv.items, arena); if (comp.clang_passthrough_mode) { child.stdin_behavior = .Inherit; child.stdout_behavior = .Inherit; diff --git a/src/main.zig b/src/main.zig index e47ff0e272..1538e86225 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3012,9 +3012,7 @@ fn runOrTest( const cmd = try std.mem.join(arena, " ", argv.items); fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd }); } else if (std.process.can_spawn) { - const child = try std.ChildProcess.init(argv.items, gpa); - defer child.deinit(); - + var child = std.ChildProcess.init(argv.items, gpa); child.stdin_behavior = .Inherit; child.stdout_behavior = .Inherit; child.stderr_behavior = .Inherit; @@ -3700,9 +3698,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi }; if (std.process.can_spawn) { - const child = try std.ChildProcess.init(child_argv, gpa); - defer child.deinit(); - + var child = std.ChildProcess.init(child_argv, gpa); child.stdin_behavior = .Inherit; child.stdout_behavior = .Inherit; child.stderr_behavior = .Inherit; diff --git a/src/mingw.zig b/src/mingw.zig index 84ec0795f1..e99a1af8fc 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -369,9 +369,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { } if (std.process.can_spawn) { - const child = try std.ChildProcess.init(&args, arena); - defer child.deinit(); - + var child = std.ChildProcess.init(&args, arena); child.stdin_behavior = .Ignore; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe; diff --git a/test/tests.zig b/test/tests.zig index 5b15da2bcb..ee4b922021 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -731,9 +731,7 @@ pub const StackTracesContext = struct { return ExecError.ExecNotSupported; } - const child = std.ChildProcess.init(args.items, b.allocator) catch unreachable; - defer child.deinit(); - + var child = std.ChildProcess.init(args.items, b.allocator); child.stdin_behavior = .Ignore; child.stdout_behavior = .Pipe; child.stderr_behavior = .Pipe;