diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index cd9fdc27d8..823e9a8b41 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -1821,8 +1821,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult { stdout_bytes = try poller.toOwnedSlice(.stdout); stderr_bytes = try poller.toOwnedSlice(.stderr); } else { - var small_buffer: [1]u8 = undefined; - var stdout_reader = stdout.readerStreaming(&small_buffer); + var stdout_reader = stdout.readerStreaming(&.{}); stdout_bytes = stdout_reader.interface.allocRemaining(arena, run.stdio_limit) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ReadFailed => return stdout_reader.err.?, @@ -1830,8 +1829,7 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult { }; } } else if (child.stderr) |stderr| { - var small_buffer: [1]u8 = undefined; - var stderr_reader = stderr.readerStreaming(&small_buffer); + var stderr_reader = stderr.readerStreaming(&.{}); stderr_bytes = stderr_reader.interface.allocRemaining(arena, run.stdio_limit) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ReadFailed => return stderr_reader.err.?, diff --git a/lib/std/Io/Reader.zig b/lib/std/Io/Reader.zig index c4923127ee..51877e0ef1 100644 --- a/lib/std/Io/Reader.zig +++ b/lib/std/Io/Reader.zig @@ -283,8 +283,6 @@ pub const LimitedAllocError = Allocator.Error || ShortError || error{StreamTooLo /// such case, the next byte that would be read will be the first one to exceed /// `limit`, and all preceeding bytes have been discarded. /// -/// Asserts `buffer` has nonzero capacity. -/// /// See also: /// * `appendRemaining` pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocError![]u8 { diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig index d9879e1e74..566607c6a4 100644 --- a/lib/std/fs/File.zig +++ b/lib/std/fs/File.zig @@ -1194,11 +1194,16 @@ pub const Reader = struct { }; } - pub fn initMode(file: File, buffer: []u8, init_mode: Reader.Mode) Reader { + /// Positional is more threadsafe, since the global seek position is not + /// affected, but when such syscalls are not available, preemptively + /// initializing in streaming mode skips a failed syscall. + pub fn initStreaming(file: File, buffer: []u8) Reader { return .{ .file = file, - .interface = initInterface(buffer), - .mode = init_mode, + .interface = Reader.initInterface(buffer), + .mode = .streaming, + .seek_err = error.Unseekable, + .size_err = error.Streaming, }; } @@ -1578,14 +1583,21 @@ pub const Writer = struct { const max_buffers_len = 16; pub fn init(file: File, buffer: []u8) Writer { - return initMode(file, buffer, .positional); - } - - pub fn initMode(file: File, buffer: []u8, init_mode: Writer.Mode) Writer { return .{ .file = file, .interface = initInterface(buffer), - .mode = init_mode, + .mode = .positional, + }; + } + + /// Positional is more threadsafe, since the global seek position is not + /// affected, but when such syscalls are not available, preemptively + /// initializing in streaming mode will skip a failed syscall. + pub fn initStreaming(file: File, buffer: []u8) Writer { + return .{ + .file = file, + .interface = initInterface(buffer), + .mode = .streaming, }; } @@ -2092,15 +2104,10 @@ pub fn reader(file: File, buffer: []u8) Reader { } /// Positional is more threadsafe, since the global seek position is not -/// affected, but when such syscalls are not available, preemptively choosing -/// `Reader.Mode.streaming` will skip a failed syscall. +/// affected, but when such syscalls are not available, preemptively +/// initializing in streaming mode skips a failed syscall. pub fn readerStreaming(file: File, buffer: []u8) Reader { - return .{ - .file = file, - .interface = Reader.initInterface(buffer), - .mode = .streaming, - .seek_err = error.Unseekable, - }; + return .initStreaming(file, buffer); } /// Defaults to positional reading; falls back to streaming. @@ -2112,10 +2119,10 @@ pub fn writer(file: File, buffer: []u8) Writer { } /// Positional is more threadsafe, since the global seek position is not -/// affected, but when such syscalls are not available, preemptively choosing -/// `Writer.Mode.streaming` will skip a failed syscall. +/// affected, but when such syscalls are not available, preemptively +/// initializing in streaming mode will skip a failed syscall. pub fn writerStreaming(file: File, buffer: []u8) Writer { - return .initMode(file, buffer, .streaming); + return .initStreaming(file, buffer); } const range_off: windows.LARGE_INTEGER = 0; diff --git a/lib/std/net.zig b/lib/std/net.zig index 0e0bae3c03..326cf99753 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -2233,7 +2233,7 @@ pub const Stream = struct { }, .buffer = buffer, }, - .file_writer = .initMode(.{ .handle = stream.handle }, &.{}, .streaming), + .file_writer = .initStreaming(.{ .handle = stream.handle }, &.{}), }; } diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index e286a4ce54..ca5e61b243 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -1003,14 +1003,14 @@ fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { fn writeIntFd(fd: i32, value: ErrInt) !void { var buffer: [8]u8 = undefined; - var fw: std.fs.File.Writer = .initMode(.{ .handle = fd }, &buffer, .streaming); + var fw: std.fs.File.Writer = .initStreaming(.{ .handle = fd }, &buffer); fw.interface.writeInt(u64, value, .little) catch unreachable; fw.interface.flush() catch return error.SystemResources; } fn readIntFd(fd: i32) !ErrInt { var buffer: [8]u8 = undefined; - var fr: std.fs.File.Reader = .initMode(.{ .handle = fd }, &buffer, .streaming); + var fr: std.fs.File.Reader = .initStreaming(.{ .handle = fd }, &buffer); return @intCast(fr.interface.takeInt(u64, .little) catch return error.SystemResources); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 71ca226cc2..ed4d73c673 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6278,7 +6278,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr try child.spawn(); - const stderr = try child.stderr.?.deprecatedReader().readAllAlloc(arena, std.math.maxInt(usize)); + var stderr_reader = child.stderr.?.readerStreaming(&.{}); + const stderr = try stderr_reader.interface.allocRemaining(arena, .limited(std.math.maxInt(u32))); const term = child.wait() catch |err| { return comp.failCObj(c_object, "failed to spawn zig clang {s}: {s}", .{ argv.items[0], @errorName(err) }); diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index 01f2e1bba3..e84519b16c 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -1632,7 +1632,7 @@ fn computeHash(f: *Fetch, pkg_path: Cache.Path, filter: Filter) RunError!Compute fn dumpHashInfo(all_files: []const *const HashedFile) !void { var stdout_buffer: [1024]u8 = undefined; - var stdout_writer: fs.File.Writer = .initMode(.stdout(), &stdout_buffer, .streaming); + var stdout_writer: fs.File.Writer = .initStreaming(.stdout(), &stdout_buffer); const w = &stdout_writer.interface; for (all_files) |hashed_file| { try w.print("{t}: {x}: {s}\n", .{ hashed_file.kind, &hashed_file.hash, hashed_file.normalized_path }); diff --git a/test/standalone/test_obj_link_run/build.zig b/test/standalone/test_obj_link_run/build.zig index 404b4b7099..45d35865c6 100644 --- a/test/standalone/test_obj_link_run/build.zig +++ b/test/standalone/test_obj_link_run/build.zig @@ -27,10 +27,7 @@ pub fn build(b: *std.Build) void { b.default_step = test_step; const test_run = b.addRunArtifact(test_exe); - if (!is_windows) { - // https://github.com/ziglang/zig/issues/24867 - test_run.addCheck(.{ .expect_stderr_match = "All 3 tests passed." }); - } + test_run.addCheck(.{ .expect_stderr_match = "All 3 tests passed." }); test_step.dependOn(&test_run.step); }