authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2022-04-29 17:07:51+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-04-29 22:50:34-04:00
loga0a2ce92ca129d28e22c63f7bace1672c43776b5
tree26bb1adc15b8dcc3aae1e38a4d57800d7319b030
parent0e49142ce478c13f3ec701900cd894b3536471a1

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);

11 files changed, 21 insertions(+), 54 deletions(-)

lib/std/build.zig+2-6
...@@ -971,9 +971,7 @@ pub const Builder = struct {...@@ -971,9 +971,7 @@ pub const Builder = struct {
971 if (!std.process.can_spawn)971 if (!std.process.can_spawn)
972 return error.ExecNotSupported;972 return error.ExecNotSupported;
973973
974 const child = std.ChildProcess.init(argv, self.allocator) catch unreachable;974 var child = std.ChildProcess.init(argv, self.allocator);
975 defer child.deinit();
976
977 child.cwd = cwd;975 child.cwd = cwd;
978 child.env_map = env_map;976 child.env_map = env_map;
979977
...@@ -1187,9 +1185,7 @@ pub const Builder = struct {...@@ -1187,9 +1185,7 @@ pub const Builder = struct {
1187 return error.ExecNotSupported;1185 return error.ExecNotSupported;
11881186
1189 const max_output_size = 400 * 1024;1187 const max_output_size = 400 * 1024;
1190 const child = try std.ChildProcess.init(argv, self.allocator);1188 var child = std.ChildProcess.init(argv, self.allocator);
1191 defer child.deinit();
1192
1193 child.stdin_behavior = .Ignore;1189 child.stdin_behavior = .Ignore;
1194 child.stdout_behavior = .Pipe;1190 child.stdout_behavior = .Pipe;
1195 child.stderr_behavior = stderr_behavior;1191 child.stderr_behavior = stderr_behavior;
lib/std/build/RunStep.zig+1-3
...@@ -184,9 +184,7 @@ fn make(step: *Step) !void {...@@ -184,9 +184,7 @@ fn make(step: *Step) !void {
184 return ExecError.ExecNotSupported;184 return ExecError.ExecNotSupported;
185 }185 }
186186
187 const child = std.ChildProcess.init(argv, self.builder.allocator) catch unreachable;187 var child = std.ChildProcess.init(argv, self.builder.allocator);
188 defer child.deinit();
189
190 child.cwd = cwd;188 child.cwd = cwd;
191 child.env_map = self.env_map orelse self.builder.env_map;189 child.env_map = self.env_map orelse self.builder.env_map;
192190
lib/std/child_process.zig+7-19
...@@ -98,10 +98,8 @@ pub const ChildProcess = struct {...@@ -98,10 +98,8 @@ pub const ChildProcess = struct {
98 };98 };
9999
100 /// First argument in argv is the executable.100 /// First argument in argv is the executable.
101 /// On success must call deinit.101 pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess {
102 pub fn init(argv: []const []const u8, allocator: mem.Allocator) !*ChildProcess {102 return .{
103 const child = try allocator.create(ChildProcess);
104 child.* = ChildProcess{
105 .allocator = allocator,103 .allocator = allocator,
106 .argv = argv,104 .argv = argv,
107 .pid = undefined,105 .pid = undefined,
...@@ -121,8 +119,6 @@ pub const ChildProcess = struct {...@@ -121,8 +119,6 @@ pub const ChildProcess = struct {
121 .stderr_behavior = StdIo.Inherit,119 .stderr_behavior = StdIo.Inherit,
122 .expand_arg0 = .no_expand,120 .expand_arg0 = .no_expand,
123 };121 };
124 errdefer allocator.destroy(child);
125 return child;
126 }122 }
127123
128 pub fn setUserName(self: *ChildProcess, name: []const u8) !void {124 pub fn setUserName(self: *ChildProcess, name: []const u8) !void {
...@@ -199,7 +195,7 @@ pub const ChildProcess = struct {...@@ -199,7 +195,7 @@ pub const ChildProcess = struct {
199 };195 };
200196
201 fn collectOutputPosix(197 fn collectOutputPosix(
202 child: *const ChildProcess,198 child: ChildProcess,
203 stdout: *std.ArrayList(u8),199 stdout: *std.ArrayList(u8),
204 stderr: *std.ArrayList(u8),200 stderr: *std.ArrayList(u8),
205 max_output_bytes: usize,201 max_output_bytes: usize,
...@@ -298,7 +294,7 @@ pub const ChildProcess = struct {...@@ -298,7 +294,7 @@ pub const ChildProcess = struct {
298 }294 }
299 }295 }
300296
301 fn collectOutputWindows(child: *const ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void {297 fn collectOutputWindows(child: ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void {
302 const bump_amt = 512;298 const bump_amt = 512;
303 const handles = [_]windows.HANDLE{299 const handles = [_]windows.HANDLE{
304 child.stdout.?.handle,300 child.stdout.?.handle,
...@@ -383,9 +379,7 @@ pub const ChildProcess = struct {...@@ -383,9 +379,7 @@ pub const ChildProcess = struct {
383 max_output_bytes: usize = 50 * 1024,379 max_output_bytes: usize = 50 * 1024,
384 expand_arg0: Arg0Expand = .no_expand,380 expand_arg0: Arg0Expand = .no_expand,
385 }) !ExecResult {381 }) !ExecResult {
386 const child = try ChildProcess.init(args.argv, args.allocator);382 var child = ChildProcess.init(args.argv, args.allocator);
387 defer child.deinit();
388
389 child.stdin_behavior = .Ignore;383 child.stdin_behavior = .Ignore;
390 child.stdout_behavior = .Pipe;384 child.stdout_behavior = .Pipe;
391 child.stderr_behavior = .Pipe;385 child.stderr_behavior = .Pipe;
...@@ -452,10 +446,6 @@ pub const ChildProcess = struct {...@@ -452,10 +446,6 @@ pub const ChildProcess = struct {
452 return self.term.?;446 return self.term.?;
453 }447 }
454448
455 pub fn deinit(self: *ChildProcess) void {
456 self.allocator.destroy(self);
457 }
458
459 fn waitUnwrappedWindows(self: *ChildProcess) !void {449 fn waitUnwrappedWindows(self: *ChildProcess) !void {
460 const result = windows.WaitForSingleObjectEx(self.handle, windows.INFINITE, false);450 const result = windows.WaitForSingleObjectEx(self.handle, windows.INFINITE, false);
461451
...@@ -1374,8 +1364,7 @@ test "build and call child_process" {...@@ -1374,8 +1364,7 @@ test "build and call child_process" {
13741364
1375 // spawn compiled file as child_process with argument 'hello world' + expect success1365 // spawn compiled file as child_process with argument 'hello world' + expect success
1376 const args = [_][]const u8{ child_path, "hello world" };1366 const args = [_][]const u8{ child_path, "hello world" };
1377 var child_proc = try ChildProcess.init(&args, allocator);1367 var child_proc = ChildProcess.init(&args, allocator);
1378 defer child_proc.deinit();
1379 const ret_val = try child_proc.spawnAndWait();1368 const ret_val = try child_proc.spawnAndWait();
1380 try testing.expectEqual(ret_val, .{ .Exited = 0 });1369 try testing.expectEqual(ret_val, .{ .Exited = 0 });
1381}1370}
...@@ -1385,11 +1374,10 @@ test "creating a child process with stdin and stdout behavior set to StdIo.Pipe"...@@ -1385,11 +1374,10 @@ test "creating a child process with stdin and stdout behavior set to StdIo.Pipe"
1385 const testing = std.testing;1374 const testing = std.testing;
1386 const allocator = testing.allocator;1375 const allocator = testing.allocator;
13871376
1388 var child_process = try std.ChildProcess.init(1377 var child_process = std.ChildProcess.init(
1389 &[_][]const u8{ testing.zig_exe_path, "fmt", "--stdin" },1378 &[_][]const u8{ testing.zig_exe_path, "fmt", "--stdin" },
1390 allocator,1379 allocator,
1391 );1380 );
1392 defer child_process.deinit();
1393 child_process.stdin_behavior = .Pipe;1381 child_process.stdin_behavior = .Pipe;
1394 child_process.stdout_behavior = .Pipe;1382 child_process.stdout_behavior = .Pipe;
13951383
lib/std/testing.zig+3-2
...@@ -442,10 +442,11 @@ pub fn buildExe(zigexec: []const u8, zigfile: []const u8, binfile: []const u8) !...@@ -442,10 +442,11 @@ pub fn buildExe(zigexec: []const u8, zigfile: []const u8, binfile: []const u8) !
442 const flag_emit = "-femit-bin=";442 const flag_emit = "-femit-bin=";
443 const cmd_emit = try std.mem.concat(allocator, u8, &[_][]const u8{ flag_emit, binfile });443 const cmd_emit = try std.mem.concat(allocator, u8, &[_][]const u8{ flag_emit, binfile });
444 defer allocator.free(cmd_emit);444 defer allocator.free(cmd_emit);
445
445 const args = [_][]const u8{ zigexec, "build-exe", zigfile, cmd_emit };446 const args = [_][]const u8{ zigexec, "build-exe", zigfile, cmd_emit };
446 var procCompileChild = try std.ChildProcess.init(&args, allocator);447 var procCompileChild = std.ChildProcess.init(&args, allocator);
447 defer procCompileChild.deinit();
448 try procCompileChild.spawn();448 try procCompileChild.spawn();
449
449 const ret_val = try procCompileChild.wait();450 const ret_val = try procCompileChild.wait();
450 try expectEqual(ret_val, .{ .Exited = 0 });451 try expectEqual(ret_val, .{ .Exited = 0 });
451}452}
src/Compilation.zig+1-3
...@@ -3611,9 +3611,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P...@@ -3611,9 +3611,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
3611 }3611 }
36123612
3613 if (std.process.can_spawn) {3613 if (std.process.can_spawn) {
3614 const child = try std.ChildProcess.init(argv.items, arena);3614 var child = std.ChildProcess.init(argv.items, arena);
3615 defer child.deinit();
3616
3617 if (comp.clang_passthrough_mode) {3615 if (comp.clang_passthrough_mode) {
3618 child.stdin_behavior = .Inherit;3616 child.stdin_behavior = .Inherit;
3619 child.stdout_behavior = .Inherit;3617 child.stdout_behavior = .Inherit;
src/link/Coff.zig+1-3
...@@ -1390,9 +1390,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -1390,9 +1390,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
1390 // If possible, we run LLD as a child process because it does not always1390 // If possible, we run LLD as a child process because it does not always
1391 // behave properly as a library, unfortunately.1391 // behave properly as a library, unfortunately.
1392 // https://github.com/ziglang/zig/issues/38251392 // https://github.com/ziglang/zig/issues/3825
1393 const child = try std.ChildProcess.init(argv.items, arena);1393 var child = std.ChildProcess.init(argv.items, arena);
1394 defer child.deinit();
1395
1396 if (comp.clang_passthrough_mode) {1394 if (comp.clang_passthrough_mode) {
1397 child.stdin_behavior = .Inherit;1395 child.stdin_behavior = .Inherit;
1398 child.stdout_behavior = .Inherit;1396 child.stdout_behavior = .Inherit;
src/link/Elf.zig+1-3
...@@ -1754,9 +1754,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1754,9 +1754,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1754 // If possible, we run LLD as a child process because it does not always1754 // If possible, we run LLD as a child process because it does not always
1755 // behave properly as a library, unfortunately.1755 // behave properly as a library, unfortunately.
1756 // https://github.com/ziglang/zig/issues/38251756 // https://github.com/ziglang/zig/issues/3825
1757 const child = try std.ChildProcess.init(argv.items, arena);1757 var child = std.ChildProcess.init(argv.items, arena);
1758 defer child.deinit();
1759
1760 if (comp.clang_passthrough_mode) {1758 if (comp.clang_passthrough_mode) {
1761 child.stdin_behavior = .Inherit;1759 child.stdin_behavior = .Inherit;
1762 child.stdout_behavior = .Inherit;1760 child.stdout_behavior = .Inherit;
src/link/Wasm.zig+1-3
...@@ -2405,9 +2405,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !...@@ -2405,9 +2405,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
2405 // If possible, we run LLD as a child process because it does not always2405 // If possible, we run LLD as a child process because it does not always
2406 // behave properly as a library, unfortunately.2406 // behave properly as a library, unfortunately.
2407 // https://github.com/ziglang/zig/issues/38252407 // https://github.com/ziglang/zig/issues/3825
2408 const child = try std.ChildProcess.init(argv.items, arena);2408 var child = std.ChildProcess.init(argv.items, arena);
2409 defer child.deinit();
2410
2411 if (comp.clang_passthrough_mode) {2409 if (comp.clang_passthrough_mode) {
2412 child.stdin_behavior = .Inherit;2410 child.stdin_behavior = .Inherit;
2413 child.stdout_behavior = .Inherit;2411 child.stdout_behavior = .Inherit;
src/main.zig+2-6
...@@ -3012,9 +3012,7 @@ fn runOrTest(...@@ -3012,9 +3012,7 @@ fn runOrTest(
3012 const cmd = try std.mem.join(arena, " ", argv.items);3012 const cmd = try std.mem.join(arena, " ", argv.items);
3013 fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd });3013 fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd });
3014 } else if (std.process.can_spawn) {3014 } else if (std.process.can_spawn) {
3015 const child = try std.ChildProcess.init(argv.items, gpa);3015 var child = std.ChildProcess.init(argv.items, gpa);
3016 defer child.deinit();
3017
3018 child.stdin_behavior = .Inherit;3016 child.stdin_behavior = .Inherit;
3019 child.stdout_behavior = .Inherit;3017 child.stdout_behavior = .Inherit;
3020 child.stderr_behavior = .Inherit;3018 child.stderr_behavior = .Inherit;
...@@ -3700,9 +3698,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi...@@ -3700,9 +3698,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
3700 };3698 };
37013699
3702 if (std.process.can_spawn) {3700 if (std.process.can_spawn) {
3703 const child = try std.ChildProcess.init(child_argv, gpa);3701 var child = std.ChildProcess.init(child_argv, gpa);
3704 defer child.deinit();
3705
3706 child.stdin_behavior = .Inherit;3702 child.stdin_behavior = .Inherit;
3707 child.stdout_behavior = .Inherit;3703 child.stdout_behavior = .Inherit;
3708 child.stderr_behavior = .Inherit;3704 child.stderr_behavior = .Inherit;
src/mingw.zig+1-3
...@@ -369,9 +369,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -369,9 +369,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
369 }369 }
370370
371 if (std.process.can_spawn) {371 if (std.process.can_spawn) {
372 const child = try std.ChildProcess.init(&args, arena);372 var child = std.ChildProcess.init(&args, arena);
373 defer child.deinit();
374
375 child.stdin_behavior = .Ignore;373 child.stdin_behavior = .Ignore;
376 child.stdout_behavior = .Pipe;374 child.stdout_behavior = .Pipe;
377 child.stderr_behavior = .Pipe;375 child.stderr_behavior = .Pipe;
test/tests.zig+1-3
...@@ -731,9 +731,7 @@ pub const StackTracesContext = struct {...@@ -731,9 +731,7 @@ pub const StackTracesContext = struct {
731 return ExecError.ExecNotSupported;731 return ExecError.ExecNotSupported;
732 }732 }
733733
734 const child = std.ChildProcess.init(args.items, b.allocator) catch unreachable;734 var child = std.ChildProcess.init(args.items, b.allocator);
735 defer child.deinit();
736
737 child.stdin_behavior = .Ignore;735 child.stdin_behavior = .Ignore;
738 child.stdout_behavior = .Pipe;736 child.stdout_behavior = .Pipe;
739 child.stderr_behavior = .Pipe;737 child.stderr_behavior = .Pipe;