aboutsummaryrefslogtreecommitdiff
path: root/lib/std/process/Child.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/process/Child.zig')
-rw-r--r--lib/std/process/Child.zig81
1 files changed, 46 insertions, 35 deletions
diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig
index c2effb523a..21cc545f12 100644
--- a/lib/std/process/Child.zig
+++ b/lib/std/process/Child.zig
@@ -14,6 +14,7 @@ const assert = std.debug.assert;
const native_os = builtin.os.tag;
const Allocator = std.mem.Allocator;
const ChildProcess = @This();
+const ArrayList = std.ArrayListUnmanaged;
pub const Id = switch (native_os) {
.windows => windows.HANDLE,
@@ -348,19 +349,6 @@ pub const RunResult = struct {
stderr: []u8,
};
-fn writeFifoDataToArrayList(allocator: Allocator, list: *std.ArrayListUnmanaged(u8), fifo: *std.io.PollFifo) !void {
- if (fifo.head != 0) fifo.realign();
- if (list.capacity == 0) {
- list.* = .{
- .items = fifo.buf[0..fifo.count],
- .capacity = fifo.buf.len,
- };
- fifo.* = std.io.PollFifo.init(fifo.allocator);
- } else {
- try list.appendSlice(allocator, fifo.buf[0..fifo.count]);
- }
-}
-
/// Collect the output from the process's stdout and stderr. Will return once all output
/// has been collected. This does not mean that the process has ended. `wait` should still
/// be called to wait for and clean up the process.
@@ -370,28 +358,48 @@ pub fn collectOutput(
child: ChildProcess,
/// Used for `stdout` and `stderr`.
allocator: Allocator,
- stdout: *std.ArrayListUnmanaged(u8),
- stderr: *std.ArrayListUnmanaged(u8),
+ stdout: *ArrayList(u8),
+ stderr: *ArrayList(u8),
max_output_bytes: usize,
) !void {
assert(child.stdout_behavior == .Pipe);
assert(child.stderr_behavior == .Pipe);
- var poller = std.io.poll(allocator, enum { stdout, stderr }, .{
+ var poller = std.Io.poll(allocator, enum { stdout, stderr }, .{
.stdout = child.stdout.?,
.stderr = child.stderr.?,
});
defer poller.deinit();
+ const stdout_r = poller.reader(.stdout);
+ stdout_r.buffer = stdout.allocatedSlice();
+ stdout_r.seek = 0;
+ stdout_r.end = stdout.items.len;
+
+ const stderr_r = poller.reader(.stderr);
+ stderr_r.buffer = stderr.allocatedSlice();
+ stderr_r.seek = 0;
+ stderr_r.end = stderr.items.len;
+
+ defer {
+ stdout.* = .{
+ .items = stdout_r.buffer[0..stdout_r.end],
+ .capacity = stdout_r.buffer.len,
+ };
+ stderr.* = .{
+ .items = stderr_r.buffer[0..stderr_r.end],
+ .capacity = stderr_r.buffer.len,
+ };
+ stdout_r.buffer = &.{};
+ stderr_r.buffer = &.{};
+ }
+
while (try poller.poll()) {
- if (poller.fifo(.stdout).count > max_output_bytes)
+ if (stdout_r.bufferedLen() > max_output_bytes)
return error.StdoutStreamTooLong;
- if (poller.fifo(.stderr).count > max_output_bytes)
+ if (stderr_r.bufferedLen() > max_output_bytes)
return error.StderrStreamTooLong;
}
-
- try writeFifoDataToArrayList(allocator, stdout, poller.fifo(.stdout));
- try writeFifoDataToArrayList(allocator, stderr, poller.fifo(.stderr));
}
pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix.PollError || error{
@@ -421,10 +429,10 @@ pub fn run(args: struct {
child.expand_arg0 = args.expand_arg0;
child.progress_node = args.progress_node;
- var stdout: std.ArrayListUnmanaged(u8) = .empty;
- errdefer stdout.deinit(args.allocator);
- var stderr: std.ArrayListUnmanaged(u8) = .empty;
- errdefer stderr.deinit(args.allocator);
+ var stdout: ArrayList(u8) = .empty;
+ defer stdout.deinit(args.allocator);
+ var stderr: ArrayList(u8) = .empty;
+ defer stderr.deinit(args.allocator);
try child.spawn();
errdefer {
@@ -432,7 +440,7 @@ pub fn run(args: struct {
}
try child.collectOutput(args.allocator, &stdout, &stderr, args.max_output_bytes);
- return RunResult{
+ return .{
.stdout = try stdout.toOwnedSlice(args.allocator),
.stderr = try stderr.toOwnedSlice(args.allocator),
.term = try child.wait(),
@@ -878,12 +886,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
var cmd_line_cache = WindowsCommandLineCache.init(self.allocator, self.argv);
defer cmd_line_cache.deinit();
- var app_buf: std.ArrayListUnmanaged(u16) = .empty;
+ var app_buf: ArrayList(u16) = .empty;
defer app_buf.deinit(self.allocator);
try app_buf.appendSlice(self.allocator, app_name_w);
- var dir_buf: std.ArrayListUnmanaged(u16) = .empty;
+ var dir_buf: ArrayList(u16) = .empty;
defer dir_buf.deinit(self.allocator);
if (cwd_path_w.len > 0) {
@@ -1003,13 +1011,16 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
}
fn writeIntFd(fd: i32, value: ErrInt) !void {
- const file: File = .{ .handle = fd };
- file.deprecatedWriter().writeInt(u64, @intCast(value), .little) catch return error.SystemResources;
+ var buffer: [8]u8 = undefined;
+ var fw: std.fs.File.Writer = .initMode(.{ .handle = fd }, &buffer, .streaming);
+ fw.interface.writeInt(u64, value, .little) catch unreachable;
+ fw.interface.flush() catch return error.SystemResources;
}
fn readIntFd(fd: i32) !ErrInt {
- const file: File = .{ .handle = fd };
- return @intCast(file.deprecatedReader().readInt(u64, .little) catch return error.SystemResources);
+ var buffer: [8]u8 = undefined;
+ var fr: std.fs.File.Reader = .initMode(.{ .handle = fd }, &buffer, .streaming);
+ return @intCast(fr.interface.takeInt(u64, .little) catch return error.SystemResources);
}
const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
@@ -1020,8 +1031,8 @@ const ErrInt = std.meta.Int(.unsigned, @sizeOf(anyerror) * 8);
/// Note: If the dir is the cwd, dir_buf should be empty (len = 0).
fn windowsCreateProcessPathExt(
allocator: mem.Allocator,
- dir_buf: *std.ArrayListUnmanaged(u16),
- app_buf: *std.ArrayListUnmanaged(u16),
+ dir_buf: *ArrayList(u16),
+ app_buf: *ArrayList(u16),
pathext: [:0]const u16,
cmd_line_cache: *WindowsCommandLineCache,
envp_ptr: ?[*]u16,
@@ -1504,7 +1515,7 @@ const WindowsCommandLineCache = struct {
/// Returns the absolute path of `cmd.exe` within the Windows system directory.
/// The caller owns the returned slice.
fn windowsCmdExePath(allocator: mem.Allocator) error{ OutOfMemory, Unexpected }![:0]u16 {
- var buf = try std.ArrayListUnmanaged(u16).initCapacity(allocator, 128);
+ var buf = try ArrayList(u16).initCapacity(allocator, 128);
errdefer buf.deinit(allocator);
while (true) {
const unused_slice = buf.unusedCapacitySlice();