authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-30 22:21:53-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-04 00:27:08-08:00
log384bfc5f99d0d46521d62e09858facc2edd3bc74
tree41085030b13fdb31a3ae2df23a10555b01701d33
parent42988fc5f43abdbac5ef5abc7cb5f74f8bc55ad4

std.Progress: go through Io interface for parent IPC mechanism

and fix start code

4 files changed, 41 insertions(+), 17 deletions(-)

lib/std/Io.zig+3-2
......@@ -724,6 +724,8 @@ pub const VTable = struct {
724724 childWait: *const fn (?*anyopaque, *std.process.Child) std.process.Child.WaitError!std.process.Child.Term,
725725 childKill: *const fn (?*anyopaque, *std.process.Child) void,
726726
727 progressParentFile: *const fn (?*anyopaque) std.Progress.ParentFileError!File,
728
727729 now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
728730 sleep: *const fn (?*anyopaque, Timeout) SleepError!void,
729731
......@@ -2241,6 +2243,5 @@ pub fn unlockStderr(io: Io) void {
22412243
22422244pub fn environ(io: Io, name: []const u8) ?[]const u8 {
22432245 _ = io;
2244 _ = name;
2245 if (true) @panic("TODO Io.environ");
2246 std.debug.panic("TODO: environ query: {s}", .{name});
22462247}
lib/std/Io/Threaded.zig+24
......@@ -82,6 +82,8 @@ pub const Environ = struct {
8282 exist: Exist = .{},
8383 /// Protected by `mutex`. Memoized based on `block`.
8484 string: String = .{},
85 /// ZIG_PROGRESS
86 zig_progress_handle: std.Progress.ParentFileError!u31 = error.EnvironmentVariableMissing,
8587 /// Protected by `mutex`. Tracks the problem, if any, that occurred when
8688 /// trying to scan environment variables.
8789 ///
......@@ -1408,6 +1410,8 @@ pub fn io(t: *Threaded) Io {
14081410 .childWait = childWait, // TODO audit for cancelation and unreachable
14091411 .childKill = childKill, // TODO audit for cancelation and unreachable
14101412
1413 .progressParentFile = progressParentFile,
1414
14111415 .now = now,
14121416 .sleep = sleep,
14131417
......@@ -1552,6 +1556,8 @@ pub fn ioBasic(t: *Threaded) Io {
15521556 .childWait = childWait,
15531557 .childKill = childKill,
15541558
1559 .progressParentFile = progressParentFile,
1560
15551561 .now = now,
15561562 .sleep = sleep,
15571563
......@@ -12685,6 +12691,8 @@ fn scanEnviron(t: *Threaded) void {
1268512691 t.environ.exist.CLICOLOR_FORCE = true;
1268612692 } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) {
1268712693 t.environ.string.PATH = value;
12694 } else if (std.mem.eql(u8, key, "ZIG_PROGRESS")) {
12695 t.environ.zig_progress_handle = std.fmt.parseInt(u31, value, 10) catch error.UnrecognizedFormat;
1268812696 }
1268912697 }
1269012698 } else {
......@@ -12704,6 +12712,8 @@ fn scanEnviron(t: *Threaded) void {
1270412712 t.environ.exist.CLICOLOR_FORCE = true;
1270512713 } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) {
1270612714 t.environ.string.PATH = value;
12715 } else if (std.mem.eql(u8, key, "ZIG_PROGRESS")) {
12716 t.environ.zig_progress_handle = std.fmt.parseInt(u31, value, 10) catch error.UnrecognizedFormat;
1270712717 }
1270812718 }
1270912719 }
......@@ -14343,6 +14353,20 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons
1434314353
1434414354var pipe_name_counter = std.atomic.Value(u32).init(1);
1434514355
14356fn progressParentFile(userdata: ?*anyopaque) std.Progress.ParentFileError!File {
14357 const t: *Threaded = @ptrCast(@alignCast(userdata));
14358
14359 t.scanEnviron();
14360
14361 const int = try t.environ.zig_progress_handle;
14362
14363 return .{ .handle = switch (@typeInfo(Io.File.Handle)) {
14364 .int => int,
14365 .pointer => @ptrFromInt(int),
14366 else => return error.UnsupportedOperation,
14367 } };
14368}
14369
1434614370test {
1434714371 _ = @import("Threaded/test.zig");
1434814372}
lib/std/Progress.zig+11-12
......@@ -422,7 +422,7 @@ pub const StartFailure = union(enum) {
422422 unstarted,
423423 spawn_ipc_worker: error{ConcurrencyUnavailable},
424424 spawn_update_worker: error{ConcurrencyUnavailable},
425 parse_env_var: error{ InvalidCharacter, Overflow },
425 parent_ipc: error{ UnsupportedOperation, UnrecognizedFormat },
426426};
427427
428428const node_storage_buffer_len = 83;
......@@ -446,6 +446,12 @@ const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {
446446 else => false,
447447};
448448
449pub const ParentFileError = error{
450 UnsupportedOperation,
451 EnvironmentVariableMissing,
452 UnrecognizedFormat,
453};
454
449455/// Initializes a global Progress instance.
450456///
451457/// Asserts there is only one global Progress instance.
......@@ -476,20 +482,13 @@ pub fn start(io: Io, options: Options) Node {
476482
477483 global_progress.io = io;
478484
479 if (std.process.Environ.parseInt(io, "ZIG_PROGRESS", u31, 10)) |ipc_fd| {
480 global_progress.update_worker = io.concurrent(ipcThreadRun, .{
481 io,
482 @as(Io.File, .{ .handle = switch (@typeInfo(Io.File.Handle)) {
483 .int => ipc_fd,
484 .pointer => @ptrFromInt(ipc_fd),
485 else => @compileError("unsupported fd_t of " ++ @typeName(Io.File.Handle)),
486 } }),
487 }) catch |err| {
485 if (io.vtable.progressParentFile(io.userdata)) |ipc_file| {
486 global_progress.update_worker = io.concurrent(ipcThreadRun, .{ io, ipc_file }) catch |err| {
488487 global_progress.start_failure = .{ .spawn_ipc_worker = err };
489488 return Node.none;
490489 };
491490 } else |env_err| switch (env_err) {
492 error.EnvironmentVariableNotFound => {
491 error.EnvironmentVariableMissing => {
493492 if (options.disable_printing) {
494493 return Node.none;
495494 }
......@@ -535,7 +534,7 @@ pub fn start(io: Io, options: Options) Node {
535534 }
536535 },
537536 else => |e| {
538 global_progress.start_failure = .{ .parse_env_var = e };
537 global_progress.start_failure = .{ .parent_ipc = e };
539538 return Node.none;
540539 },
541540 }
lib/std/start.zig+3-3
......@@ -733,11 +733,11 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
733733
734734 var threaded: std.Io.Threaded = .init(gpa, .{
735735 .argv0 = if (@sizeOf(std.Io.Threaded.Argv0) != 0) .{ .value = args[0] } else .{},
736 .environ = environ,
736 .environ = .{ .block = environ },
737737 });
738738 defer threaded.deinit();
739739
740 var env_map = environ.getEnvMap(gpa) catch |err|
740 var env_map = std.process.Environ.createMap(.{ .block = environ }, gpa) catch |err|
741741 std.process.fatal("failed to parse environment variables: {t}", .{err});
742742 defer env_map.deinit();
743743
......@@ -749,7 +749,7 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
749749 .arena = &arena_allocator,
750750 .gpa = gpa,
751751 .io = threaded.io(),
752 .env_map = env_map,
752 .env_map = &env_map,
753753 }));
754754}
755755