aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fs/file.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-03-16 04:11:41 -0400
committerGitHub <noreply@github.com>2023-03-16 04:11:41 -0400
commitbd242ce1ce9ef6ffb1af4432d892bf582dcdba8a (patch)
tree34caaa3f320e8830a5f1f1c93a4b5d70c0d192a8 /lib/std/fs/file.zig
parenta2c6ecd6dc0bdbe2396be9b055852324f16d34c9 (diff)
parent7177b3994626114e57bf8df36ca84fd942bac282 (diff)
downloadzig-bd242ce1ce9ef6ffb1af4432d892bf582dcdba8a.tar.gz
zig-bd242ce1ce9ef6ffb1af4432d892bf582dcdba8a.zip
Merge pull request #14647 from ziglang/build-parallel
zig build: run steps in parallel
Diffstat (limited to 'lib/std/fs/file.zig')
-rw-r--r--lib/std/fs/file.zig38
1 files changed, 33 insertions, 5 deletions
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig
index bf93a61239..8235b8aecf 100644
--- a/lib/std/fs/file.zig
+++ b/lib/std/fs/file.zig
@@ -1048,12 +1048,27 @@ pub const File = struct {
/// Returns the number of bytes read. If the number read is smaller than the total bytes
/// from all the buffers, it means the file reached the end. Reaching the end of a file
/// is not an error condition.
- /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
- /// order to handle partial reads from the underlying OS layer.
- /// See https://github.com/ziglang/zig/issues/7699
+ ///
+ /// The `iovecs` parameter is mutable because:
+ /// * This function needs to mutate the fields in order to handle partial
+ /// reads from the underlying OS layer.
+ /// * The OS layer expects pointer addresses to be inside the application's address space
+ /// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer
+ /// addresses when the length is zero. So this function modifies the iov_base fields
+ /// when the length is zero.
+ ///
+ /// Related open issue: https://github.com/ziglang/zig/issues/7699
pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize {
if (iovecs.len == 0) return 0;
+ // We use the address of this local variable for all zero-length
+ // vectors so that the OS does not complain that we are giving it
+ // addresses outside the application's address space.
+ var garbage: [1]u8 = undefined;
+ for (iovecs) |*v| {
+ if (v.iov_len == 0) v.iov_base = &garbage;
+ }
+
var i: usize = 0;
var off: usize = 0;
while (true) {
@@ -1181,13 +1196,26 @@ pub const File = struct {
}
}
- /// The `iovecs` parameter is mutable because this function needs to mutate the fields in
- /// order to handle partial writes from the underlying OS layer.
+ /// The `iovecs` parameter is mutable because:
+ /// * This function needs to mutate the fields in order to handle partial
+ /// writes from the underlying OS layer.
+ /// * The OS layer expects pointer addresses to be inside the application's address space
+ /// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer
+ /// addresses when the length is zero. So this function modifies the iov_base fields
+ /// when the length is zero.
/// See https://github.com/ziglang/zig/issues/7699
/// See equivalent function: `std.net.Stream.writevAll`.
pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void {
if (iovecs.len == 0) return;
+ // We use the address of this local variable for all zero-length
+ // vectors so that the OS does not complain that we are giving it
+ // addresses outside the application's address space.
+ var garbage: [1]u8 = undefined;
+ for (iovecs) |*v| {
+ if (v.iov_len == 0) v.iov_base = &garbage;
+ }
+
var i: usize = 0;
while (true) {
var amt = try self.writev(iovecs[i..]);