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 {...@@ -724,6 +724,8 @@ pub const VTable = struct {
724 childWait: *const fn (?*anyopaque, *std.process.Child) std.process.Child.WaitError!std.process.Child.Term,724 childWait: *const fn (?*anyopaque, *std.process.Child) std.process.Child.WaitError!std.process.Child.Term,
725 childKill: *const fn (?*anyopaque, *std.process.Child) void,725 childKill: *const fn (?*anyopaque, *std.process.Child) void,
726726
727 progressParentFile: *const fn (?*anyopaque) std.Progress.ParentFileError!File,
728
727 now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,729 now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
728 sleep: *const fn (?*anyopaque, Timeout) SleepError!void,730 sleep: *const fn (?*anyopaque, Timeout) SleepError!void,
729731
...@@ -2241,6 +2243,5 @@ pub fn unlockStderr(io: Io) void {...@@ -2241,6 +2243,5 @@ pub fn unlockStderr(io: Io) void {
22412243
2242pub fn environ(io: Io, name: []const u8) ?[]const u8 {2244pub fn environ(io: Io, name: []const u8) ?[]const u8 {
2243 _ = io;2245 _ = io;
2244 _ = name;2246 std.debug.panic("TODO: environ query: {s}", .{name});
2245 if (true) @panic("TODO Io.environ");
2246}2247}
lib/std/Io/Threaded.zig+24
...@@ -82,6 +82,8 @@ pub const Environ = struct {...@@ -82,6 +82,8 @@ pub const Environ = struct {
82 exist: Exist = .{},82 exist: Exist = .{},
83 /// Protected by `mutex`. Memoized based on `block`.83 /// Protected by `mutex`. Memoized based on `block`.
84 string: String = .{},84 string: String = .{},
85 /// ZIG_PROGRESS
86 zig_progress_handle: std.Progress.ParentFileError!u31 = error.EnvironmentVariableMissing,
85 /// Protected by `mutex`. Tracks the problem, if any, that occurred when87 /// Protected by `mutex`. Tracks the problem, if any, that occurred when
86 /// trying to scan environment variables.88 /// trying to scan environment variables.
87 ///89 ///
...@@ -1408,6 +1410,8 @@ pub fn io(t: *Threaded) Io {...@@ -1408,6 +1410,8 @@ pub fn io(t: *Threaded) Io {
1408 .childWait = childWait, // TODO audit for cancelation and unreachable1410 .childWait = childWait, // TODO audit for cancelation and unreachable
1409 .childKill = childKill, // TODO audit for cancelation and unreachable1411 .childKill = childKill, // TODO audit for cancelation and unreachable
14101412
1413 .progressParentFile = progressParentFile,
1414
1411 .now = now,1415 .now = now,
1412 .sleep = sleep,1416 .sleep = sleep,
14131417
...@@ -1552,6 +1556,8 @@ pub fn ioBasic(t: *Threaded) Io {...@@ -1552,6 +1556,8 @@ pub fn ioBasic(t: *Threaded) Io {
1552 .childWait = childWait,1556 .childWait = childWait,
1553 .childKill = childKill,1557 .childKill = childKill,
15541558
1559 .progressParentFile = progressParentFile,
1560
1555 .now = now,1561 .now = now,
1556 .sleep = sleep,1562 .sleep = sleep,
15571563
...@@ -12685,6 +12691,8 @@ fn scanEnviron(t: *Threaded) void {...@@ -12685,6 +12691,8 @@ fn scanEnviron(t: *Threaded) void {
12685 t.environ.exist.CLICOLOR_FORCE = true;12691 t.environ.exist.CLICOLOR_FORCE = true;
12686 } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) {12692 } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) {
12687 t.environ.string.PATH = value;12693 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;
12688 }12696 }
12689 }12697 }
12690 } else {12698 } else {
...@@ -12704,6 +12712,8 @@ fn scanEnviron(t: *Threaded) void {...@@ -12704,6 +12712,8 @@ fn scanEnviron(t: *Threaded) void {
12704 t.environ.exist.CLICOLOR_FORCE = true;12712 t.environ.exist.CLICOLOR_FORCE = true;
12705 } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) {12713 } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) {
12706 t.environ.string.PATH = value;12714 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;
12707 }12717 }
12708 }12718 }
12709 }12719 }
...@@ -14343,6 +14353,20 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons...@@ -14343,6 +14353,20 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons
1434314353
14344var pipe_name_counter = std.atomic.Value(u32).init(1);14354var 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
14346test {14370test {
14347 _ = @import("Threaded/test.zig");14371 _ = @import("Threaded/test.zig");
14348}14372}
lib/std/Progress.zig+11-12
...@@ -422,7 +422,7 @@ pub const StartFailure = union(enum) {...@@ -422,7 +422,7 @@ pub const StartFailure = union(enum) {
422 unstarted,422 unstarted,
423 spawn_ipc_worker: error{ConcurrencyUnavailable},423 spawn_ipc_worker: error{ConcurrencyUnavailable},
424 spawn_update_worker: error{ConcurrencyUnavailable},424 spawn_update_worker: error{ConcurrencyUnavailable},
425 parse_env_var: error{ InvalidCharacter, Overflow },425 parent_ipc: error{ UnsupportedOperation, UnrecognizedFormat },
426};426};
427427
428const node_storage_buffer_len = 83;428const node_storage_buffer_len = 83;
...@@ -446,6 +446,12 @@ const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {...@@ -446,6 +446,12 @@ const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {
446 else => false,446 else => false,
447};447};
448448
449pub const ParentFileError = error{
450 UnsupportedOperation,
451 EnvironmentVariableMissing,
452 UnrecognizedFormat,
453};
454
449/// Initializes a global Progress instance.455/// Initializes a global Progress instance.
450///456///
451/// Asserts there is only one global Progress instance.457/// Asserts there is only one global Progress instance.
...@@ -476,20 +482,13 @@ pub fn start(io: Io, options: Options) Node {...@@ -476,20 +482,13 @@ pub fn start(io: Io, options: Options) Node {
476482
477 global_progress.io = io;483 global_progress.io = io;
478484
479 if (std.process.Environ.parseInt(io, "ZIG_PROGRESS", u31, 10)) |ipc_fd| {485 if (io.vtable.progressParentFile(io.userdata)) |ipc_file| {
480 global_progress.update_worker = io.concurrent(ipcThreadRun, .{486 global_progress.update_worker = io.concurrent(ipcThreadRun, .{ io, ipc_file }) catch |err| {
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| {
488 global_progress.start_failure = .{ .spawn_ipc_worker = err };487 global_progress.start_failure = .{ .spawn_ipc_worker = err };
489 return Node.none;488 return Node.none;
490 };489 };
491 } else |env_err| switch (env_err) {490 } else |env_err| switch (env_err) {
492 error.EnvironmentVariableNotFound => {491 error.EnvironmentVariableMissing => {
493 if (options.disable_printing) {492 if (options.disable_printing) {
494 return Node.none;493 return Node.none;
495 }494 }
...@@ -535,7 +534,7 @@ pub fn start(io: Io, options: Options) Node {...@@ -535,7 +534,7 @@ pub fn start(io: Io, options: Options) Node {
535 }534 }
536 },535 },
537 else => |e| {536 else => |e| {
538 global_progress.start_failure = .{ .parse_env_var = e };537 global_progress.start_failure = .{ .parent_ipc = e };
539 return Node.none;538 return Node.none;
540 },539 },
541 }540 }
lib/std/start.zig+3-3
...@@ -733,11 +733,11 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B...@@ -733,11 +733,11 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
733733
734 var threaded: std.Io.Threaded = .init(gpa, .{734 var threaded: std.Io.Threaded = .init(gpa, .{
735 .argv0 = if (@sizeOf(std.Io.Threaded.Argv0) != 0) .{ .value = args[0] } else .{},735 .argv0 = if (@sizeOf(std.Io.Threaded.Argv0) != 0) .{ .value = args[0] } else .{},
736 .environ = environ,736 .environ = .{ .block = environ },
737 });737 });
738 defer threaded.deinit();738 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|
741 std.process.fatal("failed to parse environment variables: {t}", .{err});741 std.process.fatal("failed to parse environment variables: {t}", .{err});
742 defer env_map.deinit();742 defer env_map.deinit();
743743
...@@ -749,7 +749,7 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B...@@ -749,7 +749,7 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B
749 .arena = &arena_allocator,749 .arena = &arena_allocator,
750 .gpa = gpa,750 .gpa = gpa,
751 .io = threaded.io(),751 .io = threaded.io(),
752 .env_map = env_map,752 .env_map = &env_map,
753 }));753 }));
754}754}
755755