authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-10-01 10:53:39-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-10-01 10:53:39-04:00
logd1ec8377d1fcc9874c40e6603f64087f0b310677
treec96fbee62356b2ead89d8ea3f4a1d408710df7c4
parent9d4eaf1e07525a72fa54cfaa346a18bf18953af4
signaturelock-open Commit is signed but in an unrecognized format.

std lib: flesh out the async I/O streaming API a bit


7 files changed, 187 insertions(+), 71 deletions(-)

src/analyze.cpp+5
...@@ -2710,6 +2710,11 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2710,6 +2710,11 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2710 // be resolving ResolveStatusZeroBitsKnown2710 // be resolving ResolveStatusZeroBitsKnown
2711 assert(field->type_entry != nullptr);2711 assert(field->type_entry != nullptr);
27122712
2713 if (type_is_invalid(field->type_entry)) {
2714 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2715 break;
2716 }
2717
2713 if (!type_has_bits(field->type_entry))2718 if (!type_has_bits(field->type_entry))
2714 continue;2719 continue;
27152720
std/atomic/int.zig+4
...@@ -29,5 +29,9 @@ pub fn Int(comptime T: type) type {...@@ -29,5 +29,9 @@ pub fn Int(comptime T: type) type {
29 pub fn xchg(self: *Self, new_value: T) T {29 pub fn xchg(self: *Self, new_value: T) T {
30 return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);30 return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
31 }31 }
32
33 pub fn fetchAdd(self: *Self, op: T) T {
34 return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Add, op, AtomicOrder.SeqCst);
35 }
32 };36 };
33}37}
std/event/fs.zig+128-46
...@@ -30,20 +30,20 @@ pub const Request = struct {...@@ -30,20 +30,20 @@ pub const Request = struct {
3030
31 pub const PWriteV = struct {31 pub const PWriteV = struct {
32 fd: os.FileHandle,32 fd: os.FileHandle,
33 iov: []os.posix.iovec_const,33 iov: []const os.posix.iovec_const,
34 offset: usize,34 offset: usize,
35 result: Error!void,35 result: Error!void,
3636
37 pub const Error = os.File.WriteError;37 pub const Error = os.PosixWriteError;
38 };38 };
3939
40 pub const PReadV = struct {40 pub const PReadV = struct {
41 fd: os.FileHandle,41 fd: os.FileHandle,
42 iov: []os.posix.iovec,42 iov: []const os.posix.iovec,
43 offset: usize,43 offset: usize,
44 result: Error!usize,44 result: Error!usize,
4545
46 pub const Error = os.File.ReadError;46 pub const Error = os.PosixReadError;
47 };47 };
4848
49 pub const Open = struct {49 pub const Open = struct {
...@@ -72,28 +72,47 @@ pub const Request = struct {...@@ -72,28 +72,47 @@ pub const Request = struct {
72 };72 };
73};73};
7474
75pub const PWriteVError = error{OutOfMemory} || os.File.WriteError;
76
75/// data - just the inner references - must live until pwritev promise completes.77/// data - just the inner references - must live until pwritev promise completes.
76pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {78pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) PWriteVError!void {
79 // workaround for https://github.com/ziglang/zig/issues/1194
80 suspend {
81 resume @handle();
82 }
77 switch (builtin.os) {83 switch (builtin.os) {
78 builtin.Os.macosx,84 builtin.Os.macosx,
79 builtin.Os.linux,85 builtin.Os.linux,
80 => return await (async pwritevPosix(loop, fd, data, offset) catch unreachable),86 => {
81 builtin.Os.windows => return await (async pwritevWindows(loop, fd, data, offset) catch unreachable),87 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
88 defer loop.allocator.free(iovecs);
89
90 for (data) |buf, i| {
91 iovecs[i] = os.posix.iovec_const{
92 .iov_base = buf.ptr,
93 .iov_len = buf.len,
94 };
95 }
96
97 return await (async pwritevPosix(loop, fd, iovecs, offset) catch unreachable);
98 },
99 builtin.Os.windows => {
100 const data_copy = try std.mem.dupe(loop.allocator, []const u8, data);
101 defer loop.allocator.free(data_copy);
102 return await (async pwritevWindows(loop, fd, data, offset) catch unreachable);
103 },
82 else => @compileError("Unsupported OS"),104 else => @compileError("Unsupported OS"),
83 }105 }
84}106}
85107
86/// data - just the inner references - must live until pwritev promise completes.108/// data must outlive the returned promise
87pub async fn pwritevWindows(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {109pub async fn pwritevWindows(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) os.WindowsWriteError!void {
88 if (data.len == 0) return;110 if (data.len == 0) return;
89 if (data.len == 1) return await (async pwriteWindows(loop, fd, data[0], offset) catch unreachable);111 if (data.len == 1) return await (async pwriteWindows(loop, fd, data[0], offset) catch unreachable);
90112
91 const data_copy = try std.mem.dupe(loop.allocator, []const u8, data);
92 defer loop.allocator.free(data_copy);
93
94 // TODO do these in parallel113 // TODO do these in parallel
95 var off = offset;114 var off = offset;
96 for (data_copy) |buf| {115 for (data) |buf| {
97 try await (async pwriteWindows(loop, fd, buf, off) catch unreachable);116 try await (async pwriteWindows(loop, fd, buf, off) catch unreachable);
98 off += buf.len;117 off += buf.len;
99 }118 }
...@@ -144,23 +163,18 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off...@@ -144,23 +163,18 @@ pub async fn pwriteWindows(loop: *Loop, fd: os.FileHandle, data: []const u8, off
144 }163 }
145}164}
146165
147/// data - just the inner references - must live until pwritev promise completes.166/// iovecs must live until pwritev promise completes.
148pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const u8, offset: usize) !void {167pub async fn pwritevPosix(
168 loop: *Loop,
169 fd: os.FileHandle,
170 iovecs: []const posix.iovec_const,
171 offset: usize,
172) os.PosixWriteError!void {
149 // workaround for https://github.com/ziglang/zig/issues/1194173 // workaround for https://github.com/ziglang/zig/issues/1194
150 suspend {174 suspend {
151 resume @handle();175 resume @handle();
152 }176 }
153177
154 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
155 defer loop.allocator.free(iovecs);
156
157 for (data) |buf, i| {
158 iovecs[i] = os.posix.iovec_const{
159 .iov_base = buf.ptr,
160 .iov_len = buf.len,
161 };
162 }
163
164 var req_node = RequestNode{178 var req_node = RequestNode{
165 .prev = null,179 .prev = null,
166 .next = null,180 .next = null,
...@@ -192,38 +206,59 @@ pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const...@@ -192,38 +206,59 @@ pub async fn pwritevPosix(loop: *Loop, fd: os.FileHandle, data: []const []const
192 return req_node.data.msg.PWriteV.result;206 return req_node.data.msg.PWriteV.result;
193}207}
194208
209pub const PReadVError = error{OutOfMemory} || os.File.ReadError;
210
195/// data - just the inner references - must live until preadv promise completes.211/// data - just the inner references - must live until preadv promise completes.
196pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) !usize {212pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) PReadVError!usize {
213 // workaround for https://github.com/ziglang/zig/issues/1194
214 suspend {
215 resume @handle();
216 }
217
197 assert(data.len != 0);218 assert(data.len != 0);
198 switch (builtin.os) {219 switch (builtin.os) {
199 builtin.Os.macosx,220 builtin.Os.macosx,
200 builtin.Os.linux,221 builtin.Os.linux,
201 => return await (async preadvPosix(loop, fd, data, offset) catch unreachable),222 => {
202 builtin.Os.windows => return await (async preadvWindows(loop, fd, data, offset) catch unreachable),223 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
224 defer loop.allocator.free(iovecs);
225
226 for (data) |buf, i| {
227 iovecs[i] = os.posix.iovec{
228 .iov_base = buf.ptr,
229 .iov_len = buf.len,
230 };
231 }
232
233 return await (async preadvPosix(loop, fd, iovecs, offset) catch unreachable);
234 },
235 builtin.Os.windows => {
236 const data_copy = try std.mem.dupe(loop.allocator, []u8, data);
237 defer loop.allocator.free(data_copy);
238 return await (async preadvWindows(loop, fd, data_copy, offset) catch unreachable);
239 },
203 else => @compileError("Unsupported OS"),240 else => @compileError("Unsupported OS"),
204 }241 }
205}242}
206243
207pub async fn preadvWindows(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: u64) !usize {244/// data must outlive the returned promise
245pub async fn preadvWindows(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: u64) os.WindowsReadError!usize {
208 assert(data.len != 0);246 assert(data.len != 0);
209 if (data.len == 1) return await (async preadWindows(loop, fd, data[0], offset) catch unreachable);247 if (data.len == 1) return await (async preadWindows(loop, fd, data[0], offset) catch unreachable);
210248
211 const data_copy = try std.mem.dupe(loop.allocator, []u8, data);
212 defer loop.allocator.free(data_copy);
213
214 // TODO do these in parallel?249 // TODO do these in parallel?
215 var off: usize = 0;250 var off: usize = 0;
216 var iov_i: usize = 0;251 var iov_i: usize = 0;
217 var inner_off: usize = 0;252 var inner_off: usize = 0;
218 while (true) {253 while (true) {
219 const v = data_copy[iov_i];254 const v = data[iov_i];
220 const amt_read = try await (async preadWindows(loop, fd, v[inner_off .. v.len - inner_off], offset + off) catch unreachable);255 const amt_read = try await (async preadWindows(loop, fd, v[inner_off .. v.len - inner_off], offset + off) catch unreachable);
221 off += amt_read;256 off += amt_read;
222 inner_off += amt_read;257 inner_off += amt_read;
223 if (inner_off == v.len) {258 if (inner_off == v.len) {
224 iov_i += 1;259 iov_i += 1;
225 inner_off = 0;260 inner_off = 0;
226 if (iov_i == data_copy.len) {261 if (iov_i == data.len) {
227 return off;262 return off;
228 }263 }
229 }264 }
...@@ -275,23 +310,18 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6...@@ -275,23 +310,18 @@ pub async fn preadWindows(loop: *Loop, fd: os.FileHandle, data: []u8, offset: u6
275 return usize(bytes_transferred);310 return usize(bytes_transferred);
276}311}
277312
278/// data - just the inner references - must live until preadv promise completes.313/// iovecs must live until preadv promise completes
279pub async fn preadvPosix(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset: usize) !usize {314pub async fn preadvPosix(
315 loop: *Loop,
316 fd: os.FileHandle,
317 iovecs: []const posix.iovec,
318 offset: usize,
319) os.PosixReadError!usize {
280 // workaround for https://github.com/ziglang/zig/issues/1194320 // workaround for https://github.com/ziglang/zig/issues/1194
281 suspend {321 suspend {
282 resume @handle();322 resume @handle();
283 }323 }
284324
285 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
286 defer loop.allocator.free(iovecs);
287
288 for (data) |buf, i| {
289 iovecs[i] = os.posix.iovec{
290 .iov_base = buf.ptr,
291 .iov_len = buf.len,
292 };
293 }
294
295 var req_node = RequestNode{325 var req_node = RequestNode{
296 .prev = null,326 .prev = null,
297 .next = null,327 .next = null,
...@@ -1339,3 +1369,55 @@ async fn testFsWatch(loop: *Loop) !void {...@@ -1339,3 +1369,55 @@ async fn testFsWatch(loop: *Loop) !void {
13391369
1340 // TODO test deleting the file and then re-adding it. we should get events for both1370 // TODO test deleting the file and then re-adding it. we should get events for both
1341}1371}
1372
1373pub const OutStream = struct {
1374 fd: os.FileHandle,
1375 stream: Stream,
1376 loop: *Loop,
1377 offset: usize,
1378
1379 pub const Error = os.File.WriteError;
1380 pub const Stream = event.io.OutStream(Error);
1381
1382 pub fn init(loop: *Loop, fd: os.FileHandle, offset: usize) OutStream {
1383 return OutStream{
1384 .fd = fd,
1385 .loop = loop,
1386 .offset = offset,
1387 .stream = Stream{ .writeFn = writeFn },
1388 };
1389 }
1390
1391 async<*mem.Allocator> fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void {
1392 const self = @fieldParentPtr(OutStream, "stream", out_stream);
1393 const offset = self.offset;
1394 self.offset += bytes.len;
1395 return await (async pwritev(self.loop, self.fd, [][]const u8{bytes}, offset) catch unreachable);
1396 }
1397};
1398
1399pub const InStream = struct {
1400 fd: os.FileHandle,
1401 stream: Stream,
1402 loop: *Loop,
1403 offset: usize,
1404
1405 pub const Error = PReadVError; // TODO make this not have OutOfMemory
1406 pub const Stream = event.io.InStream(Error);
1407
1408 pub fn init(loop: *Loop, fd: os.FileHandle, offset: usize) InStream {
1409 return InStream{
1410 .fd = fd,
1411 .loop = loop,
1412 .offset = offset,
1413 .stream = Stream{ .readFn = readFn },
1414 };
1415 }
1416
1417 async<*mem.Allocator> fn readFn(in_stream: *Stream, bytes: []u8) Error!usize {
1418 const self = @fieldParentPtr(InStream, "stream", in_stream);
1419 const amt = try await (async preadv(self.loop, self.fd, [][]u8{bytes}, self.offset) catch unreachable);
1420 self.offset += amt;
1421 return amt;
1422 }
1423};
std/event/io.zig+15
...@@ -2,6 +2,7 @@ const std = @import("../index.zig");...@@ -2,6 +2,7 @@ const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const mem = std.mem;
56
6pub fn InStream(comptime ReadError: type) type {7pub fn InStream(comptime ReadError: type) type {
7 return struct {8 return struct {
...@@ -20,6 +21,20 @@ pub fn InStream(comptime ReadError: type) type {...@@ -20,6 +21,20 @@ pub fn InStream(comptime ReadError: type) type {
20 return await (async self.readFn(self, buffer) catch unreachable);21 return await (async self.readFn(self, buffer) catch unreachable);
21 }22 }
2223
24 pub async fn readIntLe(self: *Self, comptime T: type) !T {
25 return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
26 }
27
28 pub async fn readIntBe(self: *Self, comptime T: type) !T {
29 return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);
30 }
31
32 pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
33 var bytes: [@sizeOf(T)]u8 = undefined;
34 try await (async self.readFull(bytes[0..]) catch unreachable);
35 return mem.readInt(bytes, T, endian);
36 }
37
23 /// Same as `read` but end of stream returns `error.EndOfStream`.38 /// Same as `read` but end of stream returns `error.EndOfStream`.
24 pub async fn readFull(self: *Self, buf: []u8) !void {39 pub async fn readFull(self: *Self, buf: []u8) !void {
25 var index: usize = 0;40 var index: usize = 0;
std/os/file.zig+2-9
...@@ -365,14 +365,7 @@ pub const File = struct {...@@ -365,14 +365,7 @@ pub const File = struct {
365 }365 }
366 }366 }
367367
368 pub const ReadError = error{368 pub const ReadError = os.WindowsReadError || os.PosixReadError;
369 FileClosed,
370 InputOutput,
371 IsDir,
372 SystemResources,
373
374 Unexpected,
375 };
376369
377 pub fn read(self: File, buffer: []u8) ReadError!usize {370 pub fn read(self: File, buffer: []u8) ReadError!usize {
378 if (is_posix) {371 if (is_posix) {
...@@ -386,7 +379,7 @@ pub const File = struct {...@@ -386,7 +379,7 @@ pub const File = struct {
386 posix.EINVAL => unreachable,379 posix.EINVAL => unreachable,
387 posix.EFAULT => unreachable,380 posix.EFAULT => unreachable,
388 posix.EAGAIN => unreachable,381 posix.EAGAIN => unreachable,
389 posix.EBADF => return error.FileClosed,382 posix.EBADF => unreachable, // always a race condition
390 posix.EIO => return error.InputOutput,383 posix.EIO => return error.InputOutput,
391 posix.EISDIR => return error.IsDir,384 posix.EISDIR => return error.IsDir,
392 posix.ENOBUFS => return error.SystemResources,385 posix.ENOBUFS => return error.SystemResources,
std/os/index.zig+27-16
...@@ -72,6 +72,7 @@ pub const windowsGetQueuedCompletionStatus = windows_util.windowsGetQueuedComple...@@ -72,6 +72,7 @@ pub const windowsGetQueuedCompletionStatus = windows_util.windowsGetQueuedComple
72pub const WindowsWaitError = windows_util.WaitError;72pub const WindowsWaitError = windows_util.WaitError;
73pub const WindowsOpenError = windows_util.OpenError;73pub const WindowsOpenError = windows_util.OpenError;
74pub const WindowsWriteError = windows_util.WriteError;74pub const WindowsWriteError = windows_util.WriteError;
75pub const WindowsReadError = windows_util.ReadError;
7576
76pub const FileHandle = if (is_windows) windows.HANDLE else i32;77pub const FileHandle = if (is_windows) windows.HANDLE else i32;
7778
...@@ -227,6 +228,13 @@ pub fn close(handle: FileHandle) void {...@@ -227,6 +228,13 @@ pub fn close(handle: FileHandle) void {
227 }228 }
228}229}
229230
231pub const PosixReadError = error{
232 InputOutput,
233 SystemResources,
234 IsDir,
235 Unexpected,
236};
237
230/// Calls POSIX read, and keeps trying if it gets interrupted.238/// Calls POSIX read, and keeps trying if it gets interrupted.
231pub fn posixRead(fd: i32, buf: []u8) !void {239pub fn posixRead(fd: i32, buf: []u8) !void {
232 // Linux can return EINVAL when read amount is > 0x7ffff000240 // Linux can return EINVAL when read amount is > 0x7ffff000
...@@ -238,24 +246,27 @@ pub fn posixRead(fd: i32, buf: []u8) !void {...@@ -238,24 +246,27 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
238 const want_to_read = math.min(buf.len - index, usize(max_buf_len));246 const want_to_read = math.min(buf.len - index, usize(max_buf_len));
239 const rc = posix.read(fd, buf.ptr + index, want_to_read);247 const rc = posix.read(fd, buf.ptr + index, want_to_read);
240 const err = posix.getErrno(rc);248 const err = posix.getErrno(rc);
241 if (err > 0) {249 switch (err) {
242 return switch (err) {250 0 => {
243 posix.EINTR => continue,251 index += rc;
244 posix.EINVAL, posix.EFAULT => unreachable,252 continue;
245 posix.EAGAIN => unreachable,253 },
246 posix.EBADF => unreachable, // always a race condition254 posix.EINTR => continue,
247 posix.EIO => error.InputOutput,255 posix.EINVAL => unreachable,
248 posix.EISDIR => error.IsDir,256 posix.EFAULT => unreachable,
249 posix.ENOBUFS, posix.ENOMEM => error.SystemResources,257 posix.EAGAIN => unreachable,
250 else => unexpectedErrorPosix(err),258 posix.EBADF => unreachable, // always a race condition
251 };259 posix.EIO => return error.InputOutput,
260 posix.EISDIR => return error.IsDir,
261 posix.ENOBUFS => return error.SystemResources,
262 posix.ENOMEM => return error.SystemResources,
263 else => return unexpectedErrorPosix(err),
252 }264 }
253 index += rc;
254 }265 }
255}266}
256267
257/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.268/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
258pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u64) !usize {269pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u64) PosixReadError!usize {
259 switch (builtin.os) {270 switch (builtin.os) {
260 builtin.Os.macosx => {271 builtin.Os.macosx => {
261 // Darwin does not have preadv but it does have pread.272 // Darwin does not have preadv but it does have pread.
...@@ -284,7 +295,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6...@@ -284,7 +295,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
284 posix.EINVAL => unreachable,295 posix.EINVAL => unreachable,
285 posix.EFAULT => unreachable,296 posix.EFAULT => unreachable,
286 posix.ESPIPE => unreachable, // fd is not seekable297 posix.ESPIPE => unreachable, // fd is not seekable
287 posix.EAGAIN => unreachable, // use posixAsyncPReadV for non blocking298 posix.EAGAIN => unreachable, // this function is not for non blocking
288 posix.EBADF => unreachable, // always a race condition299 posix.EBADF => unreachable, // always a race condition
289 posix.EIO => return error.InputOutput,300 posix.EIO => return error.InputOutput,
290 posix.EISDIR => return error.IsDir,301 posix.EISDIR => return error.IsDir,
...@@ -302,7 +313,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6...@@ -302,7 +313,7 @@ pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u6
302 posix.EINTR => continue,313 posix.EINTR => continue,
303 posix.EINVAL => unreachable,314 posix.EINVAL => unreachable,
304 posix.EFAULT => unreachable,315 posix.EFAULT => unreachable,
305 posix.EAGAIN => unreachable, // use posixAsyncPReadV for non blocking316 posix.EAGAIN => unreachable, // don't call this function for non blocking
306 posix.EBADF => unreachable, // always a race condition317 posix.EBADF => unreachable, // always a race condition
307 posix.EIO => return error.InputOutput,318 posix.EIO => return error.InputOutput,
308 posix.EISDIR => return error.IsDir,319 posix.EISDIR => return error.IsDir,
...@@ -328,7 +339,7 @@ pub const PosixWriteError = error{...@@ -328,7 +339,7 @@ pub const PosixWriteError = error{
328};339};
329340
330/// Calls POSIX write, and keeps trying if it gets interrupted.341/// Calls POSIX write, and keeps trying if it gets interrupted.
331pub fn posixWrite(fd: i32, bytes: []const u8) !void {342pub fn posixWrite(fd: i32, bytes: []const u8) PosixWriteError!void {
332 // Linux can return EINVAL when write amount is > 0x7ffff000343 // Linux can return EINVAL when write amount is > 0x7ffff000
333 // See https://github.com/ziglang/zig/pull/743#issuecomment-363165856344 // See https://github.com/ziglang/zig/pull/743#issuecomment-363165856
334 const max_bytes_len = 0x7ffff000;345 const max_bytes_len = 0x7ffff000;
std/os/windows/util.zig+6
...@@ -42,6 +42,12 @@ pub fn windowsClose(handle: windows.HANDLE) void {...@@ -42,6 +42,12 @@ pub fn windowsClose(handle: windows.HANDLE) void {
42 assert(windows.CloseHandle(handle) != 0);42 assert(windows.CloseHandle(handle) != 0);
43}43}
4444
45pub const ReadError = error{
46 OperationAborted,
47 BrokenPipe,
48 Unexpected,
49};
50
45pub const WriteError = error{51pub const WriteError = error{
46 SystemResources,52 SystemResources,
47 OperationAborted,53 OperationAborted,