Commit a0a2ce92ca

Jimmi Holst Christensen <jhc@dismail.de>
2022-04-29 17:07:51
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);
1 parent 0e49142
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;
 
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;
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;
 
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 });
 }
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;
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;
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;
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;
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;
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;
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;