aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/std/child_process.zig55
-rw-r--r--lib/std/process.zig1
-rw-r--r--lib/std/std.zig1
3 files changed, 37 insertions, 20 deletions
diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig
index 7ff48a5652..dba92ab998 100644
--- a/lib/std/child_process.zig
+++ b/lib/std/child_process.zig
@@ -19,8 +19,15 @@ const maxInt = std.math.maxInt;
const assert = std.debug.assert;
pub const ChildProcess = struct {
- pid: if (builtin.os.tag == .windows) void else i32,
- handle: if (builtin.os.tag == .windows) windows.HANDLE else void,
+ pub const Id = switch (builtin.os.tag) {
+ .windows => windows.HANDLE,
+ else => os.pid_t,
+ };
+
+ /// Available after calling `spawn()`. This becomes `undefined` after calling `wait()`.
+ /// On Windows this is the hProcess.
+ /// On POSIX this is the pid.
+ id: Id,
thread_handle: if (builtin.os.tag == .windows) windows.HANDLE else void,
allocator: mem.Allocator,
@@ -105,8 +112,7 @@ pub const ChildProcess = struct {
return .{
.allocator = allocator,
.argv = argv,
- .pid = undefined,
- .handle = undefined,
+ .id = undefined,
.thread_handle = undefined,
.err_pipe = null,
.term = null,
@@ -131,6 +137,7 @@ pub const ChildProcess = struct {
}
/// On success must call `kill` or `wait`.
+ /// After spawning the `id` is available.
pub fn spawn(self: *ChildProcess) SpawnError!void {
if (!std.process.can_spawn) {
@compileError("the target operating system cannot spawn processes");
@@ -167,7 +174,7 @@ pub const ChildProcess = struct {
return term;
}
- try windows.TerminateProcess(self.handle, exit_code);
+ try windows.TerminateProcess(self.id, exit_code);
try self.waitUnwrappedWindows();
return self.term.?;
}
@@ -177,18 +184,21 @@ pub const ChildProcess = struct {
self.cleanupStreams();
return term;
}
- try os.kill(self.pid, os.SIG.TERM);
+ try os.kill(self.id, os.SIG.TERM);
try self.waitUnwrapped();
return self.term.?;
}
/// Blocks until child process terminates and then cleans up all resources.
pub fn wait(self: *ChildProcess) !Term {
- if (builtin.os.tag == .windows) {
- return self.waitWindows();
- } else {
- return self.waitPosix();
- }
+ const term = if (builtin.os.tag == .windows)
+ try self.waitWindows()
+ else
+ try self.waitPosix();
+
+ self.id = undefined;
+
+ return term;
}
pub const ExecResult = struct {
@@ -246,6 +256,11 @@ pub const ChildProcess = struct {
stderr.* = fifoToOwnedArrayList(poller.fifo(.stderr));
}
+ pub const ExecError = os.GetCwdError || os.ReadError || SpawnError || os.PollError || error{
+ StdoutStreamTooLong,
+ StderrStreamTooLong,
+ };
+
/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
/// If it succeeds, the caller owns result.stdout and result.stderr memory.
pub fn exec(args: struct {
@@ -256,7 +271,7 @@ pub const ChildProcess = struct {
env_map: ?*const EnvMap = null,
max_output_bytes: usize = 50 * 1024,
expand_arg0: Arg0Expand = .no_expand,
- }) !ExecResult {
+ }) ExecError!ExecResult {
var child = ChildProcess.init(args.argv, args.allocator);
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
@@ -304,18 +319,18 @@ pub const ChildProcess = struct {
}
fn waitUnwrappedWindows(self: *ChildProcess) !void {
- const result = windows.WaitForSingleObjectEx(self.handle, windows.INFINITE, false);
+ const result = windows.WaitForSingleObjectEx(self.id, windows.INFINITE, false);
self.term = @as(SpawnError!Term, x: {
var exit_code: windows.DWORD = undefined;
- if (windows.kernel32.GetExitCodeProcess(self.handle, &exit_code) == 0) {
+ if (windows.kernel32.GetExitCodeProcess(self.id, &exit_code) == 0) {
break :x Term{ .Unknown = 0 };
} else {
break :x Term{ .Exited = @truncate(u8, exit_code) };
}
});
- os.close(self.handle);
+ os.close(self.id);
os.close(self.thread_handle);
self.cleanupStreams();
return result;
@@ -323,9 +338,9 @@ pub const ChildProcess = struct {
fn waitUnwrapped(self: *ChildProcess) !void {
const res: os.WaitPidResult = if (comptime builtin.target.isDarwin())
- try os.posix_spawn.waitpid(self.pid, 0)
+ try os.posix_spawn.waitpid(self.id, 0)
else
- os.waitpid(self.pid, 0);
+ os.waitpid(self.id, 0);
const status = res.status;
self.cleanupStreams();
self.handleWaitResult(status);
@@ -483,7 +498,7 @@ pub const ChildProcess = struct {
self.stderr = null;
}
- self.pid = pid;
+ self.id = pid;
self.term = null;
if (self.stdin_behavior == StdIo.Pipe) {
@@ -657,7 +672,7 @@ pub const ChildProcess = struct {
self.stderr = null;
}
- self.pid = pid;
+ self.id = pid;
self.err_pipe = err_pipe;
self.term = null;
@@ -923,7 +938,7 @@ pub const ChildProcess = struct {
self.stderr = null;
}
- self.handle = piProcInfo.hProcess;
+ self.id = piProcInfo.hProcess;
self.thread_handle = piProcInfo.hThread;
self.term = null;
diff --git a/lib/std/process.zig b/lib/std/process.zig
index 777bcbbab0..eff29e86fa 100644
--- a/lib/std/process.zig
+++ b/lib/std/process.zig
@@ -9,6 +9,7 @@ const assert = std.debug.assert;
const testing = std.testing;
const child_process = @import("child_process.zig");
+pub const Child = child_process.ChildProcess;
pub const abort = os.abort;
pub const exit = os.exit;
pub const changeCurDir = os.chdir;
diff --git a/lib/std/std.zig b/lib/std/std.zig
index 4a6d330003..c1c682e224 100644
--- a/lib/std/std.zig
+++ b/lib/std/std.zig
@@ -12,6 +12,7 @@ pub const BoundedArray = @import("bounded_array.zig").BoundedArray;
pub const Build = @import("Build.zig");
pub const BufMap = @import("buf_map.zig").BufMap;
pub const BufSet = @import("buf_set.zig").BufSet;
+/// Deprecated: use `process.Child`.
pub const ChildProcess = @import("child_process.zig").ChildProcess;
pub const ComptimeStringMap = @import("comptime_string_map.zig").ComptimeStringMap;
pub const DynLib = @import("dynamic_library.zig").DynLib;