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

and fix start code
This commit is contained in:
Andrew Kelley
2025-12-30 22:21:53 -08:00
parent 42988fc5f4
commit 384bfc5f99
4 changed files with 41 additions and 17 deletions
+3 -2
View File
@@ -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});
}
+24
View File
@@ -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");
}
+11 -12
View File
@@ -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;
},
}
+3 -3
View File
@@ -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,
}));
}