authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-08 20:03:50-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:08-08:00
log4a53e5b0b4131c6b8e18bb551e8215e425f8ac71
tree4af8d360db353e40c74db394a9d03de1fdce9282
parentebdbbd20ace6e93b581b90075f52946b3832da93

fix a handful of compilation errors related to std.fs migration


24 files changed, 148 insertions(+), 133 deletions(-)

lib/compiler/resinator/cli.zig+1-1
......@@ -2010,7 +2010,7 @@ test "maybeAppendRC" {
20102010
20112011 // Now delete the file and try again. But this time change the input format
20122012 // to non-rc.
2013 try tmp.dir.deleteFile("foo");
2013 try tmp.dir.deleteFile(io, "foo");
20142014 options.input_format = .res;
20152015 try options.maybeAppendRC(io, tmp.dir);
20162016 try std.testing.expectEqualStrings("foo", options.input_source.filename);
lib/compiler/resinator/main.zig+1-1
......@@ -440,7 +440,7 @@ const IoStream = struct {
440440 // Delete the output file on error
441441 file.close(io);
442442 // Failing to delete is not really a big deal, so swallow any errors
443 Io.Dir.cwd().deleteFile(self.name) catch {};
443 Io.Dir.cwd().deleteFile(io, self.name) catch {};
444444 },
445445 .stdio, .memory, .closed => return,
446446 }
lib/compiler/std-docs.zig+9-9
......@@ -72,8 +72,8 @@ pub fn main() !void {
7272 const url_with_newline = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/\n", .{port});
7373 std.Io.File.stdout().writeAll(url_with_newline) catch {};
7474 if (should_open_browser) {
75 openBrowserTab(gpa, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| {
76 std.log.err("unable to open browser: {s}", .{@errorName(err)});
75 openBrowserTab(gpa, io, url_with_newline[0 .. url_with_newline.len - 1 :'\n']) catch |err| {
76 std.log.err("unable to open browser: {t}", .{err});
7777 };
7878 }
7979
......@@ -89,7 +89,7 @@ pub fn main() !void {
8989 while (true) {
9090 const connection = try http_server.accept();
9191 _ = std.Thread.spawn(.{}, accept, .{ &context, connection }) catch |err| {
92 std.log.err("unable to accept connection: {s}", .{@errorName(err)});
92 std.log.err("unable to accept connection: {t}", .{err});
9393 connection.stream.close(io);
9494 continue;
9595 };
......@@ -328,7 +328,7 @@ fn buildWasmBinary(
328328 child.stdin_behavior = .Pipe;
329329 child.stdout_behavior = .Pipe;
330330 child.stderr_behavior = .Pipe;
331 try child.spawn();
331 try child.spawn(io);
332332
333333 var poller = std.Io.poll(gpa, enum { stdout, stderr }, .{
334334 .stdout = child.stdout.?,
......@@ -434,13 +434,13 @@ fn sendMessage(io: Io, file: std.Io.File, tag: std.zig.Client.Message.Tag) !void
434434 };
435435}
436436
437fn openBrowserTab(gpa: Allocator, url: []const u8) !void {
437fn openBrowserTab(gpa: Allocator, io: Io, url: []const u8) !void {
438438 // Until https://github.com/ziglang/zig/issues/19205 is implemented, we
439439 // spawn a thread for this child process.
440 _ = try std.Thread.spawn(.{}, openBrowserTabThread, .{ gpa, url });
440 _ = try std.Thread.spawn(.{}, openBrowserTabThread, .{ gpa, io, url });
441441}
442442
443fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void {
443fn openBrowserTabThread(gpa: Allocator, io: Io, url: []const u8) !void {
444444 const main_exe = switch (builtin.os.tag) {
445445 .windows => "explorer",
446446 .macos => "open",
......@@ -450,6 +450,6 @@ fn openBrowserTabThread(gpa: Allocator, url: []const u8) !void {
450450 child.stdin_behavior = .Ignore;
451451 child.stdout_behavior = .Ignore;
452452 child.stderr_behavior = .Ignore;
453 try child.spawn();
454 _ = try child.wait();
453 try child.spawn(io);
454 _ = try child.wait(io);
455455}
lib/std/Build.zig+1-1
......@@ -1838,7 +1838,7 @@ pub fn runAllowFail(
18381838 child.env_map = &b.graph.env_map;
18391839
18401840 try Step.handleVerbose2(b, null, child.env_map, argv);
1841 try child.spawn();
1841 try child.spawn(io);
18421842
18431843 var stdout_reader = child.stdout.?.readerStreaming(io, &.{});
18441844 const stdout = stdout_reader.interface.allocRemaining(b.allocator, .limited(max_output_size)) catch {
lib/std/Build/Cache.zig+1-1
......@@ -1300,7 +1300,7 @@ fn testGetCurrentFileTimestamp(io: Io, dir: Io.Dir) !Io.Timestamp {
13001300 });
13011301 defer {
13021302 file.close(io);
1303 dir.deleteFile(test_out_file) catch {};
1303 dir.deleteFile(io, test_out_file) catch {};
13041304 }
13051305
13061306 return (try file.stat(io)).mtime;
lib/std/Build/Step.zig+1-1
......@@ -455,7 +455,7 @@ pub fn evalZigProcess(
455455 child.request_resource_usage_statistics = true;
456456 child.progress_node = prog_node;
457457
458 child.spawn() catch |err| return s.fail("failed to spawn zig compiler {s}: {t}", .{ argv[0], err });
458 child.spawn(io) catch |err| return s.fail("failed to spawn zig compiler {s}: {t}", .{ argv[0], err });
459459
460460 const zp = try gpa.create(ZigProcess);
461461 zp.* = .{
lib/std/Build/Step/Run.zig+2-2
......@@ -1689,7 +1689,7 @@ fn evalZigTest(
16891689 };
16901690
16911691 while (true) {
1692 try child.spawn();
1692 try child.spawn(io);
16931693 var poller = std.Io.poll(gpa, StdioPollEnum, .{
16941694 .stdout = child.stdout.?,
16951695 .stderr = child.stderr.?,
......@@ -2168,7 +2168,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !EvalGenericResult {
21682168 const io = b.graph.io;
21692169 const arena = b.allocator;
21702170
2171 try child.spawn();
2171 try child.spawn(io);
21722172 errdefer _ = child.kill(io) catch {};
21732173
21742174 try child.waitForSpawn();
lib/std/Build/WebServer.zig+1-1
......@@ -580,7 +580,7 @@ fn buildClientWasm(ws: *WebServer, arena: Allocator, optimize: std.builtin.Optim
580580 child.stdin_behavior = .Pipe;
581581 child.stdout_behavior = .Pipe;
582582 child.stderr_behavior = .Pipe;
583 try child.spawn();
583 try child.spawn(io);
584584
585585 var poller = Io.poll(gpa, enum { stdout, stderr }, .{
586586 .stdout = child.stdout.?,
lib/std/Io/Dir.zig+4-3
......@@ -1366,7 +1366,7 @@ pub fn deleteTree(dir: Dir, io: Io, sub_path: []const u8) DeleteTreeError!void {
13661366 => |e| return e,
13671367 };
13681368 } else {
1369 if (parent_dir.deleteFile(name)) {
1369 if (parent_dir.deleteFile(io, name)) {
13701370 continue :process_stack;
13711371 } else |err| switch (err) {
13721372 error.FileNotFound => continue :process_stack,
......@@ -1477,7 +1477,7 @@ fn deleteTreeMinStackSizeWithKindHint(parent: Dir, io: Io, sub_path: []const u8,
14771477 dir_name = result;
14781478 continue :scan_dir;
14791479 } else {
1480 if (dir.deleteFile(entry.name)) {
1480 if (dir.deleteFile(io, entry.name)) {
14811481 continue :dir_it;
14821482 } else |err| switch (err) {
14831483 error.FileNotFound => continue :dir_it,
......@@ -1567,7 +1567,7 @@ fn deleteTreeOpenInitialSubpath(dir: Dir, io: Io, sub_path: []const u8, kind_hin
15671567 => |e| return e,
15681568 };
15691569 } else {
1570 if (dir.deleteFile(sub_path)) {
1570 if (dir.deleteFile(io, sub_path)) {
15711571 return null;
15721572 } else |err| switch (err) {
15731573 error.FileNotFound => return null,
......@@ -1588,6 +1588,7 @@ fn deleteTreeOpenInitialSubpath(dir: Dir, io: Io, sub_path: []const u8, kind_hin
15881588 error.FileBusy,
15891589 error.BadPathName,
15901590 error.NetworkNotFound,
1591 error.Canceled,
15911592 error.Unexpected,
15921593 => |e| return e,
15931594 }
lib/std/Io/File.zig+4
......@@ -407,6 +407,10 @@ pub const Permissions = std.options.FilePermissions orelse if (is_windows) enum(
407407 return @intFromEnum(self);
408408 }
409409
410 pub fn fromMode(mode: std.posix.mode_t) @This() {
411 return @enumFromInt(mode);
412 }
413
410414 /// Returns `true` if and only if no class has write permissions.
411415 pub fn readOnly(self: @This()) bool {
412416 const mode = toMode(self);
lib/std/Io/File/Atomic.zig+5-2
......@@ -20,7 +20,7 @@ pub const InitError = File.OpenError;
2020pub fn init(
2121 io: Io,
2222 dest_basename: []const u8,
23 mode: File.Mode,
23 permissions: File.Permissions,
2424 dir: Dir,
2525 close_dir_on_deinit: bool,
2626 write_buffer: []u8,
......@@ -28,7 +28,10 @@ pub fn init(
2828 while (true) {
2929 const random_integer = std.crypto.random.int(u64);
3030 const tmp_sub_path = std.fmt.hex(random_integer);
31 const file = dir.createFile(io, &tmp_sub_path, .{ .mode = mode, .exclusive = true }) catch |err| switch (err) {
31 const file = dir.createFile(io, &tmp_sub_path, .{
32 .permissions = permissions,
33 .exclusive = true,
34 }) catch |err| switch (err) {
3235 error.PathAlreadyExists => continue,
3336 else => |e| return e,
3437 };
lib/std/Io/net/test.zig+1-1
......@@ -278,7 +278,7 @@ test "listen on a unix socket, send bytes, receive bytes" {
278278 defer testing.allocator.free(socket_path);
279279
280280 const socket_addr = try net.UnixAddress.init(socket_path);
281 defer Io.Dir.cwd().deleteFile(socket_path) catch {};
281 defer Io.Dir.cwd().deleteFile(io, socket_path) catch {};
282282
283283 var server = try socket_addr.listen(io, .{});
284284 defer server.socket.close(io);
lib/std/Io/test.zig+1-1
......@@ -60,7 +60,7 @@ test "write a file, read it, then delete it" {
6060 try expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], &data));
6161 try expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
6262 }
63 try tmp.dir.deleteFile(tmp_file_name);
63 try tmp.dir.deleteFile(io, tmp_file_name);
6464}
6565
6666test "File seek ops" {
lib/std/fs/test.zig+13-13
......@@ -873,7 +873,7 @@ test "file operations on directories" {
873873 try ctx.dir.makeDir(io, test_dir_name, .default_dir);
874874
875875 try testing.expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{}));
876 try testing.expectError(error.IsDir, ctx.dir.deleteFile(test_dir_name));
876 try testing.expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name));
877877 switch (native_os) {
878878 .dragonfly, .netbsd => {
879879 // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732
......@@ -942,7 +942,7 @@ test "deleteDir" {
942942 try testing.expectError(error.DirNotEmpty, ctx.dir.deleteDir(test_dir_path));
943943
944944 // deleting an empty directory
945 try ctx.dir.deleteFile(test_file_path);
945 try ctx.dir.deleteFile(io, test_file_path);
946946 try ctx.dir.deleteDir(test_dir_path);
947947 }
948948 }.impl);
......@@ -1671,13 +1671,13 @@ test "copyFile" {
16711671 const dest_file2 = try ctx.transformPath("tmp_test_copy_file3.txt");
16721672
16731673 try ctx.dir.writeFile(io, .{ .sub_path = src_file, .data = data });
1674 defer ctx.dir.deleteFile(src_file) catch {};
1674 defer ctx.dir.deleteFile(io, src_file) catch {};
16751675
16761676 try ctx.dir.copyFile(src_file, ctx.dir, dest_file, .{});
1677 defer ctx.dir.deleteFile(dest_file) catch {};
1677 defer ctx.dir.deleteFile(io, dest_file) catch {};
16781678
16791679 try ctx.dir.copyFile(src_file, ctx.dir, dest_file2, .{ .override_mode = File.default_mode });
1680 defer ctx.dir.deleteFile(dest_file2) catch {};
1680 defer ctx.dir.deleteFile(io, dest_file2) catch {};
16811681
16821682 try expectFileContents(io, ctx.dir, dest_file, data);
16831683 try expectFileContents(io, ctx.dir, dest_file2, data);
......@@ -1713,7 +1713,7 @@ test "AtomicFile" {
17131713 const content = try ctx.dir.readFileAlloc(io, test_out_file, allocator, .limited(9999));
17141714 try testing.expectEqualStrings(test_content, content);
17151715
1716 try ctx.dir.deleteFile(test_out_file);
1716 try ctx.dir.deleteFile(io, test_out_file);
17171717 }
17181718 }.impl);
17191719}
......@@ -2055,7 +2055,7 @@ test "'.' and '..' in Io.Dir functions" {
20552055 try ctx.dir.rename(copy_path, ctx.dir, rename_path, io);
20562056 const renamed_file = try ctx.dir.openFile(io, rename_path, .{});
20572057 renamed_file.close(io);
2058 try ctx.dir.deleteFile(rename_path);
2058 try ctx.dir.deleteFile(io, rename_path);
20592059
20602060 try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" });
20612061 var dir = ctx.dir;
......@@ -2113,19 +2113,19 @@ test "chmod" {
21132113 var tmp = tmpDir(.{});
21142114 defer tmp.cleanup();
21152115
2116 const file = try tmp.dir.createFile(io, "test_file", .{ .mode = 0o600 });
2116 const file = try tmp.dir.createFile(io, "test_file", .{ .permissions = .fromMode(0o600) });
21172117 defer file.close(io);
2118 try testing.expectEqual(@as(File.Mode, 0o600), (try file.stat(io)).mode & 0o7777);
2118 try testing.expectEqual(@as(posix.mode_t, 0o600), (try file.stat(io)).permissions.toMode() & 0o7777);
21192119
2120 try file.chmod(0o644);
2121 try testing.expectEqual(@as(File.Mode, 0o644), (try file.stat(io)).mode & 0o7777);
2120 try file.setPermissions(io, .fromMode(0o644));
2121 try testing.expectEqual(@as(posix.mode_t, 0o644), (try file.stat(io)).permissions.toMode() & 0o7777);
21222122
21232123 try tmp.dir.makeDir(io, "test_dir", .default_dir);
21242124 var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true });
21252125 defer dir.close(io);
21262126
2127 try dir.chmod(0o700);
2128 try testing.expectEqual(@as(File.Mode, 0o700), (try dir.stat(io)).mode & 0o7777);
2127 try dir.setPermissions(io, .fromMode(0o700));
2128 try testing.expectEqual(@as(posix.mode_t, 0o700), (try dir.stat(io)).permissions.toMode() & 0o7777);
21292129}
21302130
21312131test "chown" {
lib/std/posix/test.zig+1-1
......@@ -144,7 +144,7 @@ test "linkat with different directories" {
144144
145145 const subdir = try tmp.dir.makeOpenPath("subdir", .{});
146146
147 defer tmp.dir.deleteFile(target_name) catch {};
147 defer tmp.dir.deleteFile(io, target_name) catch {};
148148 try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" });
149149
150150 // Test 1: link from file in subdir back up to target in parent directory
lib/std/process/Child.zig+47-47
......@@ -1,4 +1,4 @@
1const ChildProcess = @This();
1const Child = @This();
22
33const builtin = @import("builtin");
44const native_os = builtin.os.tag;
......@@ -31,7 +31,7 @@ pub const Id = switch (native_os) {
3131id: Id,
3232thread_handle: if (native_os == .windows) windows.HANDLE else void,
3333
34allocator: mem.Allocator,
34allocator: Allocator,
3535
3636/// The writing end of the child process's standard input pipe.
3737/// Usage requires `stdin_behavior == StdIo.Pipe`.
......@@ -229,7 +229,7 @@ pub const StdIo = enum {
229229};
230230
231231/// First argument in argv is the executable.
232pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess {
232pub fn init(argv: []const []const u8, allocator: Allocator) Child {
233233 return .{
234234 .allocator = allocator,
235235 .argv = argv,
......@@ -252,7 +252,7 @@ pub fn init(argv: []const []const u8, allocator: mem.Allocator) ChildProcess {
252252 };
253253}
254254
255pub fn setUserName(self: *ChildProcess, name: []const u8) !void {
255pub fn setUserName(self: *Child, name: []const u8) !void {
256256 const user_info = try process.getUserInfo(name);
257257 self.uid = user_info.uid;
258258 self.gid = user_info.gid;
......@@ -260,7 +260,7 @@ pub fn setUserName(self: *ChildProcess, name: []const u8) !void {
260260
261261/// On success must call `kill` or `wait`.
262262/// After spawning the `id` is available.
263pub fn spawn(self: *ChildProcess) SpawnError!void {
263pub fn spawn(self: *Child, io: Io) SpawnError!void {
264264 if (!process.can_spawn) {
265265 @compileError("the target operating system cannot spawn processes");
266266 }
......@@ -268,17 +268,17 @@ pub fn spawn(self: *ChildProcess) SpawnError!void {
268268 if (native_os == .windows) {
269269 return self.spawnWindows();
270270 } else {
271 return self.spawnPosix();
271 return self.spawnPosix(io);
272272 }
273273}
274274
275pub fn spawnAndWait(self: *ChildProcess) SpawnError!Term {
276 try self.spawn();
277 return self.wait();
275pub fn spawnAndWait(child: *Child, io: Io) SpawnError!Term {
276 try child.spawn(io);
277 return child.wait(io);
278278}
279279
280280/// Forcibly terminates child process and then cleans up all resources.
281pub fn kill(self: *ChildProcess, io: Io) !Term {
281pub fn kill(self: *Child, io: Io) !Term {
282282 if (native_os == .windows) {
283283 return self.killWindows(io, 1);
284284 } else {
......@@ -286,7 +286,7 @@ pub fn kill(self: *ChildProcess, io: Io) !Term {
286286 }
287287}
288288
289pub fn killWindows(self: *ChildProcess, io: Io, exit_code: windows.UINT) !Term {
289pub fn killWindows(self: *Child, io: Io, exit_code: windows.UINT) !Term {
290290 if (self.term) |term| {
291291 self.cleanupStreams(io);
292292 return term;
......@@ -308,7 +308,7 @@ pub fn killWindows(self: *ChildProcess, io: Io, exit_code: windows.UINT) !Term {
308308 return self.term.?;
309309}
310310
311pub fn killPosix(self: *ChildProcess, io: Io) !Term {
311pub fn killPosix(self: *Child, io: Io) !Term {
312312 if (self.term) |term| {
313313 self.cleanupStreams(io);
314314 return term;
......@@ -325,7 +325,7 @@ pub const WaitError = SpawnError || std.os.windows.GetProcessMemoryInfoError;
325325
326326/// On some targets, `spawn` may not report all spawn errors, such as `error.InvalidExe`.
327327/// This function will block until any spawn errors can be reported, and return them.
328pub fn waitForSpawn(self: *ChildProcess) SpawnError!void {
328pub fn waitForSpawn(self: *Child) SpawnError!void {
329329 if (native_os == .windows) return; // `spawn` reports everything
330330 if (self.term) |term| {
331331 _ = term catch |spawn_err| return spawn_err;
......@@ -355,7 +355,7 @@ pub fn waitForSpawn(self: *ChildProcess) SpawnError!void {
355355}
356356
357357/// Blocks until child process terminates and then cleans up all resources.
358pub fn wait(self: *ChildProcess, io: Io) WaitError!Term {
358pub fn wait(self: *Child, io: Io) WaitError!Term {
359359 try self.waitForSpawn(); // report spawn errors
360360 if (self.term) |term| {
361361 self.cleanupStreams(io);
......@@ -381,7 +381,7 @@ pub const RunResult = struct {
381381///
382382/// The process must be started with stdout_behavior and stderr_behavior == .Pipe
383383pub fn collectOutput(
384 child: ChildProcess,
384 child: Child,
385385 /// Used for `stdout` and `stderr`.
386386 allocator: Allocator,
387387 stdout: *ArrayList(u8),
......@@ -446,7 +446,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct {
446446 expand_arg0: Arg0Expand = .no_expand,
447447 progress_node: std.Progress.Node = std.Progress.Node.none,
448448}) RunError!RunResult {
449 var child = ChildProcess.init(args.argv, allocator);
449 var child = Child.init(args.argv, allocator);
450450 child.stdin_behavior = .Ignore;
451451 child.stdout_behavior = .Pipe;
452452 child.stderr_behavior = .Pipe;
......@@ -461,7 +461,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct {
461461 var stderr: ArrayList(u8) = .empty;
462462 defer stderr.deinit(allocator);
463463
464 try child.spawn();
464 try child.spawn(io);
465465 errdefer {
466466 _ = child.kill(io) catch {};
467467 }
......@@ -474,7 +474,7 @@ pub fn run(allocator: Allocator, io: Io, args: struct {
474474 };
475475}
476476
477fn waitUnwrappedWindows(self: *ChildProcess, io: Io) WaitError!void {
477fn waitUnwrappedWindows(self: *Child, io: Io) WaitError!void {
478478 const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false);
479479
480480 self.term = @as(SpawnError!Term, x: {
......@@ -496,7 +496,7 @@ fn waitUnwrappedWindows(self: *ChildProcess, io: Io) WaitError!void {
496496 return result;
497497}
498498
499fn waitUnwrappedPosix(self: *ChildProcess, io: Io) void {
499fn waitUnwrappedPosix(self: *Child, io: Io) void {
500500 const res: posix.WaitPidResult = res: {
501501 if (self.request_resource_usage_statistics) {
502502 switch (native_os) {
......@@ -531,11 +531,11 @@ fn waitUnwrappedPosix(self: *ChildProcess, io: Io) void {
531531 self.handleWaitResult(status);
532532}
533533
534fn handleWaitResult(self: *ChildProcess, status: u32) void {
534fn handleWaitResult(self: *Child, status: u32) void {
535535 self.term = statusToTerm(status);
536536}
537537
538fn cleanupStreams(self: *ChildProcess, io: Io) void {
538fn cleanupStreams(self: *Child, io: Io) void {
539539 if (self.stdin) |*stdin| {
540540 stdin.close(io);
541541 self.stdin = null;
......@@ -561,7 +561,7 @@ fn statusToTerm(status: u32) Term {
561561 Term{ .Unknown = status };
562562}
563563
564fn spawnPosix(self: *ChildProcess) SpawnError!void {
564fn spawnPosix(self: *Child, io: Io) SpawnError!void {
565565 // The child process does need to access (one end of) these pipes. However,
566566 // we must initially set CLOEXEC to avoid a race condition. If another thread
567567 // is racing to spawn a different child process, we don't want it to inherit
......@@ -659,7 +659,7 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void {
659659 })).ptr;
660660 } else {
661661 // TODO come up with a solution for this.
662 @panic("missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process");
662 @panic("missing std lib enhancement: std.process.Child implementation has no way to collect the environment variables to forward to the child process");
663663 }
664664 };
665665
......@@ -671,41 +671,41 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void {
671671 const pid_result = try posix.fork();
672672 if (pid_result == 0) {
673673 // we are the child
674 setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
675 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
676 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
674 setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch |err| forkChildErrReport(io, err_pipe[1], err);
675 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(io, err_pipe[1], err);
676 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(io, err_pipe[1], err);
677677
678678 if (self.cwd_dir) |cwd| {
679 posix.fchdir(cwd.handle) catch |err| forkChildErrReport(err_pipe[1], err);
679 posix.fchdir(cwd.handle) catch |err| forkChildErrReport(io, err_pipe[1], err);
680680 } else if (self.cwd) |cwd| {
681 posix.chdir(cwd) catch |err| forkChildErrReport(err_pipe[1], err);
681 posix.chdir(cwd) catch |err| forkChildErrReport(io, err_pipe[1], err);
682682 }
683683
684684 // Must happen after fchdir above, the cwd file descriptor might be
685685 // equal to prog_fileno and be clobbered by this dup2 call.
686 if (prog_pipe[1] != -1) posix.dup2(prog_pipe[1], prog_fileno) catch |err| forkChildErrReport(err_pipe[1], err);
686 if (prog_pipe[1] != -1) posix.dup2(prog_pipe[1], prog_fileno) catch |err| forkChildErrReport(io, err_pipe[1], err);
687687
688688 if (self.gid) |gid| {
689 posix.setregid(gid, gid) catch |err| forkChildErrReport(err_pipe[1], err);
689 posix.setregid(gid, gid) catch |err| forkChildErrReport(io, err_pipe[1], err);
690690 }
691691
692692 if (self.uid) |uid| {
693 posix.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
693 posix.setreuid(uid, uid) catch |err| forkChildErrReport(io, err_pipe[1], err);
694694 }
695695
696696 if (self.pgid) |pid| {
697 posix.setpgid(0, pid) catch |err| forkChildErrReport(err_pipe[1], err);
697 posix.setpgid(0, pid) catch |err| forkChildErrReport(io, err_pipe[1], err);
698698 }
699699
700700 if (self.start_suspended) {
701 posix.kill(posix.getpid(), .STOP) catch |err| forkChildErrReport(err_pipe[1], err);
701 posix.kill(posix.getpid(), .STOP) catch |err| forkChildErrReport(io, err_pipe[1], err);
702702 }
703703
704704 const err = switch (self.expand_arg0) {
705705 .expand => posix.execvpeZ_expandArg0(.expand, argv_buf.ptr[0].?, argv_buf.ptr, envp),
706706 .no_expand => posix.execvpeZ_expandArg0(.no_expand, argv_buf.ptr[0].?, argv_buf.ptr, envp),
707707 };
708 forkChildErrReport(err_pipe[1], err);
708 forkChildErrReport(io, err_pipe[1], err);
709709 }
710710
711711 // we are the parent
......@@ -750,7 +750,7 @@ fn spawnPosix(self: *ChildProcess) SpawnError!void {
750750 self.progress_node.setIpcFd(prog_pipe[0]);
751751}
752752
753fn spawnWindows(self: *ChildProcess) SpawnError!void {
753fn spawnWindows(self: *Child) SpawnError!void {
754754 var saAttr = windows.SECURITY_ATTRIBUTES{
755755 .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES),
756756 .bInheritHandle = windows.TRUE,
......@@ -880,7 +880,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
880880 const app_name_wtf8 = self.argv[0];
881881 const app_name_is_absolute = fs.path.isAbsolute(app_name_wtf8);
882882
883 // the cwd set in ChildProcess is in effect when choosing the executable path
883 // the cwd set in Child is in effect when choosing the executable path
884884 // to match posix semantics
885885 var cwd_path_w_needs_free = false;
886886 const cwd_path_w = x: {
......@@ -965,7 +965,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
965965 // If the app name had path separators, that disallows PATH searching,
966966 // and there's no need to search the PATH if the app name is absolute.
967967 // We still search the path if the cwd is absolute because of the
968 // "cwd set in ChildProcess is in effect when choosing the executable path
968 // "cwd set in Child is in effect when choosing the executable path
969969 // to match posix semantics" behavior--we don't want to skip searching
970970 // the PATH just because we were trying to set the cwd of the child process.
971971 if (app_dirname_w != null or app_name_is_absolute) {
......@@ -1039,8 +1039,8 @@ fn destroyPipe(pipe: [2]posix.fd_t) void {
10391039
10401040// Child of fork calls this to report an error to the fork parent.
10411041// Then the child exits.
1042fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
1043 writeIntFd(fd, @as(ErrInt, @intFromError(err))) catch {};
1042fn forkChildErrReport(io: Io, fd: i32, err: Child.SpawnError) noreturn {
1043 writeIntFd(io, fd, @as(ErrInt, @intFromError(err))) catch {};
10441044 // If we're linking libc, some naughty applications may have registered atexit handlers
10451045 // which we really do not want to run in the fork child. I caught LLVM doing this and
10461046 // it caused a deadlock instead of doing an exit syscall. In the words of Avril Lavigne,
......@@ -1052,9 +1052,9 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
10521052 posix.system.exit(1);
10531053}
10541054
1055fn writeIntFd(fd: i32, value: ErrInt) !void {
1055fn writeIntFd(io: Io, fd: i32, value: ErrInt) !void {
10561056 var buffer: [8]u8 = undefined;
1057 var fw: File.Writer = .initStreaming(.{ .handle = fd }, &buffer);
1057 var fw: File.Writer = .initStreaming(.{ .handle = fd }, io, &buffer);
10581058 fw.interface.writeInt(u64, value, .little) catch unreachable;
10591059 fw.interface.flush() catch return error.SystemResources;
10601060}
......@@ -1078,7 +1078,7 @@ const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
10781078/// Note: `app_buf` should not contain any leading path separators.
10791079/// Note: If the dir is the cwd, dir_buf should be empty (len = 0).
10801080fn windowsCreateProcessPathExt(
1081 allocator: mem.Allocator,
1081 allocator: Allocator,
10821082 dir_buf: *ArrayList(u16),
10831083 app_buf: *ArrayList(u16),
10841084 pathext: [:0]const u16,
......@@ -1525,9 +1525,9 @@ const WindowsCommandLineCache = struct {
15251525 script_cmd_line: ?[:0]u16 = null,
15261526 cmd_exe_path: ?[:0]u16 = null,
15271527 argv: []const []const u8,
1528 allocator: mem.Allocator,
1528 allocator: Allocator,
15291529
1530 fn init(allocator: mem.Allocator, argv: []const []const u8) WindowsCommandLineCache {
1530 fn init(allocator: Allocator, argv: []const []const u8) WindowsCommandLineCache {
15311531 return .{
15321532 .allocator = allocator,
15331533 .argv = argv,
......@@ -1571,7 +1571,7 @@ const WindowsCommandLineCache = struct {
15711571
15721572/// Returns the absolute path of `cmd.exe` within the Windows system directory.
15731573/// The caller owns the returned slice.
1574fn windowsCmdExePath(allocator: mem.Allocator) error{ OutOfMemory, Unexpected }![:0]u16 {
1574fn windowsCmdExePath(allocator: Allocator) error{ OutOfMemory, Unexpected }![:0]u16 {
15751575 var buf = try ArrayList(u16).initCapacity(allocator, 128);
15761576 errdefer buf.deinit(allocator);
15771577 while (true) {
......@@ -1608,7 +1608,7 @@ const ArgvToCommandLineError = error{ OutOfMemory, InvalidWtf8, InvalidArg0 };
16081608///
16091609/// When executing `.bat`/`.cmd` scripts, use `argvToScriptCommandLineWindows` instead.
16101610fn argvToCommandLineWindows(
1611 allocator: mem.Allocator,
1611 allocator: Allocator,
16121612 argv: []const []const u8,
16131613) ArgvToCommandLineError![:0]u16 {
16141614 var buf = std.array_list.Managed(u8).init(allocator);
......@@ -1784,7 +1784,7 @@ const ArgvToScriptCommandLineError = error{
17841784/// Should only be used when spawning `.bat`/`.cmd` scripts, see `argvToCommandLineWindows` otherwise.
17851785/// The `.bat`/`.cmd` file must be known to both have the `.bat`/`.cmd` extension and exist on the filesystem.
17861786fn argvToScriptCommandLineWindows(
1787 allocator: mem.Allocator,
1787 allocator: Allocator,
17881788 /// Path to the `.bat`/`.cmd` script. If this path is relative, it is assumed to be relative to the CWD.
17891789 /// The script must have been verified to exist at this path before calling this function.
17901790 script_path: []const u16,
lib/std/tar.zig+18-18
......@@ -610,7 +610,7 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp
610610 }
611611 },
612612 .file => {
613 if (createDirAndFile(io, dir, file_name, fileMode(file.mode, options))) |fs_file| {
613 if (createDirAndFile(io, dir, file_name, filePermissions(file.mode, options))) |fs_file| {
614614 defer fs_file.close(io);
615615 var file_writer = fs_file.writer(io, &file_contents_buffer);
616616 try it.streamRemaining(file, &file_writer.interface);
......@@ -638,12 +638,12 @@ pub fn pipeToFileSystem(io: Io, dir: Io.Dir, reader: *Io.Reader, options: PipeOp
638638 }
639639}
640640
641fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, mode: Io.File.Mode) !Io.File {
642 const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode }) catch |err| {
641fn createDirAndFile(io: Io, dir: Io.Dir, file_name: []const u8, permissions: Io.File.Permissions) !Io.File {
642 const fs_file = dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions }) catch |err| {
643643 if (err == error.FileNotFound) {
644644 if (std.fs.path.dirname(file_name)) |dir_name| {
645645 try dir.makePath(io, dir_name);
646 return try dir.createFile(io, file_name, .{ .exclusive = true, .mode = mode });
646 return try dir.createFile(io, file_name, .{ .exclusive = true, .permissions = permissions });
647647 }
648648 }
649649 return err;
......@@ -880,9 +880,9 @@ test "create file and symlink" {
880880 var root = testing.tmpDir(.{});
881881 defer root.cleanup();
882882
883 var file = try createDirAndFile(io, root.dir, "file1", default_mode);
883 var file = try createDirAndFile(io, root.dir, "file1", .default_file);
884884 file.close(io);
885 file = try createDirAndFile(io, root.dir, "a/b/c/file2", default_mode);
885 file = try createDirAndFile(io, root.dir, "a/b/c/file2", .default_file);
886886 file.close(io);
887887
888888 createDirAndSymlink(io, root.dir, "a/b/c/file2", "symlink1") catch |err| {
......@@ -894,7 +894,7 @@ test "create file and symlink" {
894894
895895 // Danglink symlnik, file created later
896896 try createDirAndSymlink(io, root.dir, "../../../g/h/i/file4", "j/k/l/symlink3");
897 file = try createDirAndFile(io, root.dir, "g/h/i/file4", default_mode);
897 file = try createDirAndFile(io, root.dir, "g/h/i/file4", .default_file);
898898 file.close(io);
899899}
900900
......@@ -1118,30 +1118,30 @@ fn normalizePath(bytes: []u8) []u8 {
11181118 return bytes;
11191119}
11201120
1121const default_mode = Io.File.default_mode;
1122
11231121// File system mode based on tar header mode and mode_mode options.
1124fn fileMode(mode: u32, options: PipeOptions) Io.File.Mode {
1122fn filePermissions(mode: u32, options: PipeOptions) Io.File.Permissions {
1123 const default_mode = 0o666;
1124
11251125 if (!std.fs.has_executable_bit or options.mode_mode == .ignore)
1126 return default_mode;
1126 return .fromMode(default_mode);
11271127
11281128 const S = std.posix.S;
11291129
11301130 // The mode from the tar file is inspected for the owner executable bit.
11311131 if (mode & S.IXUSR == 0)
1132 return default_mode;
1132 return .fromMode(default_mode);
11331133
11341134 // This bit is copied to the group and other executable bits.
11351135 // Other bits of the mode are left as the default when creating files.
1136 return default_mode | S.IXUSR | S.IXGRP | S.IXOTH;
1136 return .fromMode(default_mode | S.IXUSR | S.IXGRP | S.IXOTH);
11371137}
11381138
1139test fileMode {
1139test filePermissions {
11401140 if (!std.fs.has_executable_bit) return error.SkipZigTest;
1141 try testing.expectEqual(default_mode, fileMode(0o744, PipeOptions{ .mode_mode = .ignore }));
1142 try testing.expectEqual(0o777, fileMode(0o744, PipeOptions{}));
1143 try testing.expectEqual(0o666, fileMode(0o644, PipeOptions{}));
1144 try testing.expectEqual(0o666, fileMode(0o655, PipeOptions{}));
1141 try testing.expectEqual(0o666, filePermissions(0o744, PipeOptions{ .mode_mode = .ignore }));
1142 try testing.expectEqual(0o777, filePermissions(0o744, PipeOptions{}));
1143 try testing.expectEqual(0o666, filePermissions(0o644, PipeOptions{}));
1144 try testing.expectEqual(0o666, filePermissions(0o655, PipeOptions{}));
11451145}
11461146
11471147test "executable bit" {
src/Compilation.zig+8-7
......@@ -5782,7 +5782,7 @@ pub fn translateC(
57825782 }
57835783
57845784 // Just to save disk space, we delete the file because it is never needed again.
5785 cache_tmp_dir.deleteFile(dep_basename) catch |err| {
5785 cache_tmp_dir.deleteFile(io, dep_basename) catch |err| {
57865786 log.warn("failed to delete '{s}': {t}", .{ dep_file_path, err });
57875787 };
57885788 }
......@@ -6314,11 +6314,11 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
63146314 }
63156315
63166316 // Just to save disk space, we delete the files that are never needed again.
6317 defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(diag_file_path)) catch |err| switch (err) {
6317 defer if (out_diag_path) |diag_file_path| zig_cache_tmp_dir.deleteFile(io, fs.path.basename(diag_file_path)) catch |err| switch (err) {
63186318 error.FileNotFound => {}, // the file wasn't created due to an error we reported
63196319 else => log.warn("failed to delete '{s}': {s}", .{ diag_file_path, @errorName(err) }),
63206320 };
6321 defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(fs.path.basename(dep_file_path)) catch |err| switch (err) {
6321 defer if (out_dep_path) |dep_file_path| zig_cache_tmp_dir.deleteFile(io, fs.path.basename(dep_file_path)) catch |err| switch (err) {
63226322 error.FileNotFound => {}, // the file wasn't created due to an error we reported
63236323 else => log.warn("failed to delete '{s}': {s}", .{ dep_file_path, @errorName(err) }),
63246324 };
......@@ -6329,7 +6329,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
63296329 child.stdout_behavior = .Inherit;
63306330 child.stderr_behavior = .Inherit;
63316331
6332 const term = child.spawnAndWait() catch |err| {
6332 const term = child.spawnAndWait(io) catch |err| {
63336333 return comp.failCObj(c_object, "failed to spawn zig clang (passthrough mode) {s}: {s}", .{ argv.items[0], @errorName(err) });
63346334 };
63356335 switch (term) {
......@@ -6347,7 +6347,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
63476347 child.stdout_behavior = .Ignore;
63486348 child.stderr_behavior = .Pipe;
63496349
6350 try child.spawn();
6350 try child.spawn(io);
63516351
63526352 var stderr_reader = child.stderr.?.readerStreaming(io, &.{});
63536353 const stderr = try stderr_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32)));
......@@ -6723,6 +6723,7 @@ fn spawnZigRc(
67236723 argv: []const []const u8,
67246724 child_progress_node: std.Progress.Node,
67256725) !void {
6726 const io = comp.io;
67266727 var node_name: std.ArrayList(u8) = .empty;
67276728 defer node_name.deinit(arena);
67286729
......@@ -6732,8 +6733,8 @@ fn spawnZigRc(
67326733 child.stderr_behavior = .Pipe;
67336734 child.progress_node = child_progress_node;
67346735
6735 child.spawn() catch |err| {
6736 return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {s}", .{ argv[0], @errorName(err) });
6736 child.spawn(io) catch |err| {
6737 return comp.failWin32Resource(win32_resource, "unable to spawn {s} rc: {t}", .{ argv[0], err });
67376738 };
67386739
67396740 var poller = std.Io.poll(comp.gpa, enum { stdout, stderr }, .{
src/Package/Fetch.zig+6-6
......@@ -1347,7 +1347,7 @@ fn unzip(
13471347 .diagnostics = &diagnostics,
13481348 }) catch |err| return f.fail(f.location_tok, try eb.printString("zip extract failed: {t}", .{err}));
13491349
1350 cache_root.handle.deleteFile(&zip_path) catch |err|
1350 cache_root.handle.deleteFile(io, &zip_path) catch |err|
13511351 return f.fail(f.location_tok, try eb.printString("delete temporary zip failed: {t}", .{err}));
13521352
13531353 return .{ .root_dir = diagnostics.root_dir };
......@@ -1547,7 +1547,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute
15471547 .fs_path = fs_path,
15481548 .failure = undefined, // to be populated by the worker
15491549 };
1550 group.async(io, workerDeleteFile, .{ root_dir, deleted_file });
1550 group.async(io, workerDeleteFile, .{ io, root_dir, deleted_file });
15511551 try deleted_files.append(deleted_file);
15521552 continue;
15531553 }
......@@ -1669,8 +1669,8 @@ fn workerHashFile(dir: Io.Dir, hashed_file: *HashedFile) void {
16691669 hashed_file.failure = hashFileFallible(dir, hashed_file);
16701670}
16711671
1672fn workerDeleteFile(dir: Io.Dir, deleted_file: *DeletedFile) void {
1673 deleted_file.failure = deleteFileFallible(dir, deleted_file);
1672fn workerDeleteFile(io: Io, dir: Io.Dir, deleted_file: *DeletedFile) void {
1673 deleted_file.failure = deleteFileFallible(io, dir, deleted_file);
16741674}
16751675
16761676fn hashFileFallible(io: Io, dir: Io.Dir, hashed_file: *HashedFile) HashedFile.Error!void {
......@@ -1712,8 +1712,8 @@ fn hashFileFallible(io: Io, dir: Io.Dir, hashed_file: *HashedFile) HashedFile.Er
17121712 hashed_file.size = file_size;
17131713}
17141714
1715fn deleteFileFallible(dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void {
1716 try dir.deleteFile(deleted_file.fs_path);
1715fn deleteFileFallible(io: Io, dir: Io.Dir, deleted_file: *DeletedFile) DeletedFile.Error!void {
1716 try dir.deleteFile(io, deleted_file.fs_path);
17171717}
17181718
17191719fn setExecutable(file: Io.File) !void {
src/link.zig+9-5
......@@ -1235,22 +1235,26 @@ pub const File = struct {
12351235 ty: InternPool.Index,
12361236 };
12371237
1238 pub fn determineMode(
1238 pub fn determinePermissions(
12391239 output_mode: std.builtin.OutputMode,
12401240 link_mode: std.builtin.LinkMode,
1241 ) Io.File.Mode {
1241 ) Io.File.Permissions {
12421242 // On common systems with a 0o022 umask, 0o777 will still result in a file created
12431243 // with 0o755 permissions, but it works appropriately if the system is configured
12441244 // more leniently. As another data point, C's fopen seems to open files with the
12451245 // 666 mode.
1246 const executable_mode = if (builtin.target.os.tag == .windows) 0 else 0o777;
1246 const executable_mode: Io.FilePermissions = if (builtin.target.os.tag == .windows)
1247 .default_file
1248 else
1249 .fromMode(0o777);
1250
12471251 switch (output_mode) {
12481252 .Lib => return switch (link_mode) {
12491253 .dynamic => executable_mode,
1250 .static => Io.File.default_mode,
1254 .static => .default_file,
12511255 },
12521256 .Exe => return executable_mode,
1253 .Obj => return Io.File.default_mode,
1257 .Obj => return .default_file,
12541258 }
12551259 }
12561260
src/link/Lld.zig+4-4
......@@ -1608,13 +1608,13 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi
16081608 child.stdout_behavior = .Inherit;
16091609 child.stderr_behavior = .Inherit;
16101610
1611 break :term child.spawnAndWait();
1611 break :term child.spawnAndWait(io);
16121612 } else term: {
16131613 child.stdin_behavior = .Ignore;
16141614 child.stdout_behavior = .Ignore;
16151615 child.stderr_behavior = .Pipe;
16161616
1617 child.spawn() catch |err| break :term err;
1617 child.spawn(io) catch |err| break :term err;
16181618 var stderr_reader = child.stderr.?.readerStreaming(io, &.{});
16191619 stderr = try stderr_reader.interface.allocRemaining(comp.gpa, .unlimited);
16201620 break :term child.wait();
......@@ -1658,13 +1658,13 @@ fn spawnLld(comp: *Compilation, arena: Allocator, argv: []const []const u8) !voi
16581658 rsp_child.stdout_behavior = .Inherit;
16591659 rsp_child.stderr_behavior = .Inherit;
16601660
1661 break :term rsp_child.spawnAndWait() catch |err| break :err err;
1661 break :term rsp_child.spawnAndWait(io) catch |err| break :err err;
16621662 } else {
16631663 rsp_child.stdin_behavior = .Ignore;
16641664 rsp_child.stdout_behavior = .Ignore;
16651665 rsp_child.stderr_behavior = .Pipe;
16661666
1667 rsp_child.spawn() catch |err| break :err err;
1667 rsp_child.spawn(io) catch |err| break :err err;
16681668 var stderr_reader = rsp_child.stderr.?.readerStreaming(io, &.{});
16691669 stderr = try stderr_reader.interface.allocRemaining(comp.gpa, .unlimited);
16701670 break :term rsp_child.wait() catch |err| break :err err;
src/main.zig+7-6
......@@ -4457,7 +4457,7 @@ fn runOrTest(
44574457 const term_result = t: {
44584458 std.debug.lockStdErr();
44594459 defer std.debug.unlockStdErr();
4460 break :t child.spawnAndWait();
4460 break :t child.spawnAndWait(io);
44614461 };
44624462 const term = term_result catch |err| {
44634463 try warnAboutForeignBinaries(io, arena, arg_mode, target, link_libc);
......@@ -4512,6 +4512,7 @@ fn runOrTestHotSwap(
45124512 all_args: []const []const u8,
45134513 runtime_args_start: ?usize,
45144514) !std.process.Child.Id {
4515 const io = comp.io;
45154516 const lf = comp.bin_file.?;
45164517
45174518 const exe_path = switch (builtin.target.os.tag) {
......@@ -4593,7 +4594,7 @@ fn runOrTestHotSwap(
45934594 child.stdout_behavior = .Inherit;
45944595 child.stderr_behavior = .Inherit;
45954596
4596 try child.spawn();
4597 try child.spawn(io);
45974598
45984599 return child.id;
45994600 },
......@@ -5419,8 +5420,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
54195420 const term = t: {
54205421 std.debug.lockStdErr();
54215422 defer std.debug.unlockStdErr();
5422 break :t child.spawnAndWait() catch |err| {
5423 fatal("failed to spawn build runner {s}: {s}", .{ child_argv.items[0], @errorName(err) });
5423 break :t child.spawnAndWait(io) catch |err| {
5424 fatal("failed to spawn build runner {s}: {t}", .{ child_argv.items[0], err });
54245425 };
54255426 };
54265427
......@@ -5444,7 +5445,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8)
54445445 dirs.local_cache, tmp_sub_path, @errorName(err),
54455446 });
54465447 };
5447 dirs.local_cache.handle.deleteFile(tmp_sub_path) catch {};
5448 dirs.local_cache.handle.deleteFile(io, tmp_sub_path) catch {};
54485449
54495450 var it = mem.splitScalar(u8, stdout, '\n');
54505451 var any_errors = false;
......@@ -5685,7 +5686,7 @@ fn jitCmd(
56855686 child.stdout_behavior = if (options.capture == null) .Inherit else .Pipe;
56865687 child.stderr_behavior = .Inherit;
56875688
5688 try child.spawn();
5689 try child.spawn(io);
56895690
56905691 if (options.capture) |ptr| {
56915692 var stdout_reader = child.stdout.?.readerStreaming(io, &.{});
test/src/Cases.zig+2-1
......@@ -461,6 +461,7 @@ pub fn lowerToBuildSteps(
461461 parent_step: *std.Build.Step,
462462 options: CaseTestOptions,
463463) void {
464 const io = self.io;
464465 const host = b.resolveTargetQuery(.{});
465466 const cases_dir_path = b.build_root.join(b.allocator, &.{ "test", "cases" }) catch @panic("OOM");
466467
......@@ -595,7 +596,7 @@ pub fn lowerToBuildSteps(
595596 },
596597 .Execution => |expected_stdout| no_exec: {
597598 const run = if (case.target.result.ofmt == .c) run_step: {
598 if (getExternalExecutor(&host.result, &case.target.result, .{ .link_libc = true }) != .native) {
599 if (getExternalExecutor(io, &host.result, &case.target.result, .{ .link_libc = true }) != .native) {
599600 // We wouldn't be able to run the compiled C code.
600601 break :no_exec;
601602 }
test/standalone/child_process/main.zig+1-1
......@@ -29,7 +29,7 @@ pub fn main() !void {
2929 child.stdin_behavior = .Pipe;
3030 child.stdout_behavior = .Pipe;
3131 child.stderr_behavior = .Inherit;
32 try child.spawn();
32 try child.spawn(io);
3333 const child_stdin = child.stdin.?;
3434 try child_stdin.writeAll("hello from stdin"); // verified in child
3535 child_stdin.close(io);