diff --git a/lib/std/Io.zig b/lib/std/Io.zig index f7de23aa54..2f1a180fc5 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -724,6 +724,8 @@ pub const VTable = struct { childWait: *const fn (?*anyopaque, *std.process.Child) std.process.Child.WaitError!std.process.Child.Term, childKill: *const fn (?*anyopaque, *std.process.Child) void, + progressParentFile: *const fn (?*anyopaque) std.Progress.ParentFileError!File, + now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp, sleep: *const fn (?*anyopaque, Timeout) SleepError!void, @@ -2241,6 +2243,5 @@ pub fn unlockStderr(io: Io) void { pub fn environ(io: Io, name: []const u8) ?[]const u8 { _ = io; - _ = name; - if (true) @panic("TODO Io.environ"); + std.debug.panic("TODO: environ query: {s}", .{name}); } diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 499ba76ef4..7333e9bb10 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -82,6 +82,8 @@ pub const Environ = struct { exist: Exist = .{}, /// Protected by `mutex`. Memoized based on `block`. string: String = .{}, + /// ZIG_PROGRESS + zig_progress_handle: std.Progress.ParentFileError!u31 = error.EnvironmentVariableMissing, /// Protected by `mutex`. Tracks the problem, if any, that occurred when /// trying to scan environment variables. /// @@ -1408,6 +1410,8 @@ pub fn io(t: *Threaded) Io { .childWait = childWait, // TODO audit for cancelation and unreachable .childKill = childKill, // TODO audit for cancelation and unreachable + .progressParentFile = progressParentFile, + .now = now, .sleep = sleep, @@ -1552,6 +1556,8 @@ pub fn ioBasic(t: *Threaded) Io { .childWait = childWait, .childKill = childKill, + .progressParentFile = progressParentFile, + .now = now, .sleep = sleep, @@ -12685,6 +12691,8 @@ fn scanEnviron(t: *Threaded) void { t.environ.exist.CLICOLOR_FORCE = true; } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) { t.environ.string.PATH = value; + } else if (std.mem.eql(u8, key, "ZIG_PROGRESS")) { + t.environ.zig_progress_handle = std.fmt.parseInt(u31, value, 10) catch error.UnrecognizedFormat; } } } else { @@ -12704,6 +12712,8 @@ fn scanEnviron(t: *Threaded) void { t.environ.exist.CLICOLOR_FORCE = true; } else if (@hasField(Environ.String, "PATH") and std.mem.eql(u8, key, "PATH")) { t.environ.string.PATH = value; + } else if (std.mem.eql(u8, key, "ZIG_PROGRESS")) { + t.environ.zig_progress_handle = std.fmt.parseInt(u31, value, 10) catch error.UnrecognizedFormat; } } } @@ -14343,6 +14353,20 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons var pipe_name_counter = std.atomic.Value(u32).init(1); +fn progressParentFile(userdata: ?*anyopaque) std.Progress.ParentFileError!File { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + + t.scanEnviron(); + + const int = try t.environ.zig_progress_handle; + + return .{ .handle = switch (@typeInfo(Io.File.Handle)) { + .int => int, + .pointer => @ptrFromInt(int), + else => return error.UnsupportedOperation, + } }; +} + test { _ = @import("Threaded/test.zig"); } diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index 94fd6b47a0..75ef13ca91 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -422,7 +422,7 @@ pub const StartFailure = union(enum) { unstarted, spawn_ipc_worker: error{ConcurrencyUnavailable}, spawn_update_worker: error{ConcurrencyUnavailable}, - parse_env_var: error{ InvalidCharacter, Overflow }, + parent_ipc: error{ UnsupportedOperation, UnrecognizedFormat }, }; const node_storage_buffer_len = 83; @@ -446,6 +446,12 @@ const noop_impl = builtin.single_threaded or switch (builtin.os.tag) { else => false, }; +pub const ParentFileError = error{ + UnsupportedOperation, + EnvironmentVariableMissing, + UnrecognizedFormat, +}; + /// Initializes a global Progress instance. /// /// Asserts there is only one global Progress instance. @@ -476,20 +482,13 @@ pub fn start(io: Io, options: Options) Node { global_progress.io = io; - if (std.process.Environ.parseInt(io, "ZIG_PROGRESS", u31, 10)) |ipc_fd| { - global_progress.update_worker = io.concurrent(ipcThreadRun, .{ - io, - @as(Io.File, .{ .handle = switch (@typeInfo(Io.File.Handle)) { - .int => ipc_fd, - .pointer => @ptrFromInt(ipc_fd), - else => @compileError("unsupported fd_t of " ++ @typeName(Io.File.Handle)), - } }), - }) catch |err| { + if (io.vtable.progressParentFile(io.userdata)) |ipc_file| { + global_progress.update_worker = io.concurrent(ipcThreadRun, .{ io, ipc_file }) catch |err| { global_progress.start_failure = .{ .spawn_ipc_worker = err }; return Node.none; }; } else |env_err| switch (env_err) { - error.EnvironmentVariableNotFound => { + error.EnvironmentVariableMissing => { if (options.disable_printing) { return Node.none; } @@ -535,7 +534,7 @@ pub fn start(io: Io, options: Options) Node { } }, else => |e| { - global_progress.start_failure = .{ .parse_env_var = e }; + global_progress.start_failure = .{ .parent_ipc = e }; return Node.none; }, } diff --git a/lib/std/start.zig b/lib/std/start.zig index 4c2d47b42f..e0a910f753 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -733,11 +733,11 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B var threaded: std.Io.Threaded = .init(gpa, .{ .argv0 = if (@sizeOf(std.Io.Threaded.Argv0) != 0) .{ .value = args[0] } else .{}, - .environ = environ, + .environ = .{ .block = environ }, }); defer threaded.deinit(); - var env_map = environ.getEnvMap(gpa) catch |err| + var env_map = std.process.Environ.createMap(.{ .block = environ }, gpa) catch |err| std.process.fatal("failed to parse environment variables: {t}", .{err}); defer env_map.deinit(); @@ -749,7 +749,7 @@ inline fn callMain(args: std.process.Args.Vector, environ: std.process.Environ.B .arena = &arena_allocator, .gpa = gpa, .io = threaded.io(), - .env_map = env_map, + .env_map = &env_map, })); }