From e85c89630e78ccc0e4bab44064779a07a029cecd Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Tue, 16 Jun 2020 22:38:51 +0200 Subject: [PATCH 01/14] accept Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 34 ++++++++++++++++++++++++++++++++++ lib/std/net.zig | 15 ++++++++++----- lib/std/os.zig | 7 +------ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index c547f50365..f44b2f06e4 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -720,6 +720,40 @@ pub const Loop = struct { } } + /// ------- I/0 APIs ------- + pub fn accept( + self: *Loop, + /// This argument is a socket that has been created with `socket`, bound to a local address + /// with `bind`, and is listening for connections after a `listen`. + sockfd: os.fd_t, + /// This argument is a pointer to a sockaddr structure. This structure is filled in with the + /// address of the peer socket, as known to the communications layer. The exact format of the + /// address returned addr is determined by the socket's address family (see `socket` and the + /// respective protocol man pages). + addr: *os.sockaddr, + /// This argument is a value-result argument: the caller must initialize it to contain the + /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size + /// of the peer address. + /// + /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size` + /// will return a value greater than was supplied to the call. + addr_size: *os.socklen_t, + /// The following values can be bitwise ORed in flags to obtain different behavior: + /// * `SOCK_CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the + /// description of the `O_CLOEXEC` flag in `open` for reasons why this may be useful. + flags: u32, + ) os.AcceptError!os.fd_t { + while (true) { + return os.accept(sockfd, addr, addr_size, flags | os.SOCK_NONBLOCK) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdReadable(sockfd); + continue; + }, + else => return err, + }; + } + } + /// Performs an async `os.open` using a separate thread. pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t { var req_node = Request.Node{ diff --git a/lib/std/net.zig b/lib/std/net.zig index 45d8f07f04..6b6d234843 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -1661,18 +1661,23 @@ pub const StreamServer = struct { /// If this function succeeds, the returned `Connection` is a caller-managed resource. pub fn accept(self: *StreamServer) AcceptError!Connection { - const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; - const accept_flags = nonblock | os.SOCK_CLOEXEC; var accepted_addr: Address = undefined; var adr_len: os.socklen_t = @sizeOf(Address); - if (os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| { + const accept_result = blk: { + if (std.io.is_async) { + const loop = std.event.Loop.instance orelse return error.UnexpectedError; + break :blk loop.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC); + } else { + break :blk os.accept(self.sockfd.?, &accepted_addr.any, &adr_len, os.SOCK_CLOEXEC); + } + }; + + if (accept_result) |fd| { return Connection{ .file = fs.File{ .handle = fd }, .address = accepted_addr, }; } else |err| switch (err) { - // We only give SOCK_NONBLOCK when I/O mode is async, in which case this error - // is handled by os.accept4. error.WouldBlock => unreachable, else => |e| return e, } diff --git a/lib/std/os.zig b/lib/std/os.zig index 0b09b1f82a..c5c34d4f40 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2890,12 +2890,7 @@ pub fn accept( return fd; }, EINTR => continue, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdReadable(sockfd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => unreachable, // always a race condition ECONNABORTED => return error.ConnectionAborted, EFAULT => unreachable, From 730428bfd615cab415b2942fc9b781428a0ff692 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Tue, 16 Jun 2020 22:39:09 +0200 Subject: [PATCH 02/14] connect Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 10 ++++++++++ lib/std/net.zig | 18 ++++++++++++------ lib/std/os.zig | 6 +----- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index f44b2f06e4..2dc1d5659e 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -754,6 +754,16 @@ pub const Loop = struct { } } + pub fn connect(self: *Loop, sockfd: os.socket_t, sock_addr: *const os.sockaddr, len: os.socklen_t) os.ConnectError!void { + os.connect(sockfd, sock_addr, len) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdWritable(sockfd); + return os.getsockoptError(sockfd); + }, + else => return err, + }; + } + /// Performs an async `os.open` using a separate thread. pub fn openZ(self: *Loop, file_path: [*:0]const u8, flags: u32, mode: os.mode_t) os.OpenError!os.fd_t { var req_node = Request.Node{ diff --git a/lib/std/net.zig b/lib/std/net.zig index 6b6d234843..928ebbbce5 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -614,11 +614,11 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { var addr = try std.net.Address.initUnix(path); - try os.connect( - sockfd, - &addr.any, - addr.getOsSockLen(), - ); + if (std.io.is_async) { + try loop.connect(sockfd, &addr.any, addr.getOsSockLen()); + } else { + try os.connect(sockfd, &addr.any, addr.getOsSockLen()); + } return fs.File{ .handle = sockfd, @@ -677,7 +677,13 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC); const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP); errdefer os.close(sockfd); - try os.connect(sockfd, &address.any, address.getOsSockLen()); + + if (std.io.is_async) { + const loop = std.event.Loop.instance orelse return error.WouldBlock; + try loop.connect(sockfd, &address.any, address.getOsSockLen()); + } else { + try os.connect(sockfd, &address.any, address.getOsSockLen()); + } return fs.File{ .handle = sockfd }; } diff --git a/lib/std/os.zig b/lib/std/os.zig index c5c34d4f40..023c1d5971 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3108,11 +3108,7 @@ pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) Con EADDRINUSE => return error.AddressInUse, EADDRNOTAVAIL => return error.AddressNotAvailable, EAFNOSUPPORT => return error.AddressFamilyNotSupported, - EAGAIN, EINPROGRESS => { - const loop = std.event.Loop.instance orelse return error.WouldBlock; - loop.waitUntilFdWritable(sockfd); - return getsockoptError(sockfd); - }, + EAGAIN, EINPROGRESS => return error.WouldBlock, EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. EBADF => unreachable, // sockfd is not a valid open file descriptor. ECONNREFUSED => return error.ConnectionRefused, From 08364ac773bdc95b9407974b5c761dbdab863f4d Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Tue, 16 Jun 2020 23:14:05 +0200 Subject: [PATCH 03/14] read Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 40 ++++++++++++++++++++++++++-------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 2dc1d5659e..7adc6e3a8f 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -822,23 +822,35 @@ pub const Loop = struct { /// Performs an async `os.read` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn read(self: *Loop, fd: os.fd_t, buf: []u8) os.ReadError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .read = .{ - .fd = fd, - .buf = buf, - .result = undefined, + pub fn read(self: *Loop, fd: os.fd_t, buf: []u8, simulate_evented: bool) os.ReadError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .read = .{ + .fd = fd, + .buf = buf, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.read.result; + } else { + while (true) { + return os.read(fd, buf) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdReadable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.read.result; } /// Performs an async `os.readv` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 73babf5fa2..bd0b8a2943 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -414,10 +414,12 @@ pub const File = struct { pub fn read(self: File, buffer: []u8) ReadError!usize { if (is_windows) { return windows.ReadFile(self.handle, buffer, null, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.read(self.handle, buffer); - } else { + } + + if (self.intended_io_mode == .blocking or !std.io.is_async) { return os.read(self.handle, buffer); + } else { + return std.event.Loop.instance.?.read(self.handle, buffer, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index 023c1d5971..7db545a17c 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -366,12 +366,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdReadable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForReading, // Can be a race condition. EIO => return error.InputOutput, EISDIR => return error.IsDir, From bc35435ca6e51d0e120538398e3c708ada57f6de Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 19 Jun 2020 23:00:17 +0200 Subject: [PATCH 04/14] readv Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 40 ++++++++++++++++++++++++++-------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 7adc6e3a8f..96774e3f11 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -855,23 +855,35 @@ pub const Loop = struct { /// Performs an async `os.readv` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn readv(self: *Loop, fd: os.fd_t, iov: []const os.iovec) os.ReadError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .readv = .{ - .fd = fd, - .iov = iov, - .result = undefined, + pub fn readv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, simulate_evented: bool) os.ReadError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .readv = .{ + .fd = fd, + .iov = iov, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.readv.result; + } else { + while (true) { + return os.readv(fd, iov) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdReadable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.readv.result; } /// Performs an async `os.pread` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index bd0b8a2943..51ad931504 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -463,10 +463,12 @@ pub const File = struct { if (iovecs.len == 0) return @as(usize, 0); const first = iovecs[0]; return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.readv(self.handle, iovecs); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.readv(self.handle, iovecs); + } else { + return std.event.Loop.instance.?.readv(self.handle, iovecs, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index 7db545a17c..e5a06965d8 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -423,12 +423,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdReadable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForReading, // can be a race condition EIO => return error.InputOutput, EISDIR => return error.IsDir, From bd9f2369d5c4e5fcd38342c877f9ae6531f78909 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 19 Jun 2020 23:08:34 +0200 Subject: [PATCH 05/14] pread Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 42 +++++++++++++++++++++++++++--------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 96774e3f11..27c00b9ab3 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -888,24 +888,36 @@ pub const Loop = struct { /// Performs an async `os.pread` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn pread(self: *Loop, fd: os.fd_t, buf: []u8, offset: u64) os.PReadError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .pread = .{ - .fd = fd, - .buf = buf, - .offset = offset, - .result = undefined, + pub fn pread(self: *Loop, fd: os.fd_t, buf: []u8, offset: u64, simulate_evented: bool) os.PReadError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .pread = .{ + .fd = fd, + .buf = buf, + .offset = offset, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.pread.result; + } else { + while (true) { + return os.pread(fd, buf, offset) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdReadable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.pread.result; } /// Performs an async `os.preadv` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 51ad931504..cb3b41ffdf 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -438,10 +438,12 @@ pub const File = struct { pub fn pread(self: File, buffer: []u8, offset: u64) PReadError!usize { if (is_windows) { return windows.ReadFile(self.handle, buffer, offset, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.pread(self.handle, buffer, offset); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.pread(self.handle, buffer, offset); + } else { + return std.event.Loop.instance.?.pread(self.handle, buffer, offset, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index e5a06965d8..6ed555011e 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -482,12 +482,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdReadable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForReading, // Can be a race condition. EIO => return error.InputOutput, EISDIR => return error.IsDir, From 59ecdaea127cb680d295ad02319dacba75ac1e73 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 19 Jun 2020 23:13:54 +0200 Subject: [PATCH 06/14] preadv Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 42 +++++++++++++++++++++++++++--------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 27c00b9ab3..a14e798c50 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -922,24 +922,36 @@ pub const Loop = struct { /// Performs an async `os.preadv` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn preadv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, offset: u64) os.ReadError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .preadv = .{ - .fd = fd, - .iov = iov, - .offset = offset, - .result = undefined, + pub fn preadv(self: *Loop, fd: os.fd_t, iov: []const os.iovec, offset: u64, simulate_evented: bool) os.ReadError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .preadv = .{ + .fd = fd, + .iov = iov, + .offset = offset, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.preadv.result; + } else { + while (true) { + return os.preadv(fd, iov, offset) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdReadable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.preadv.result; } /// Performs an async `os.write` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index cb3b41ffdf..4aa33fc5b9 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -506,10 +506,12 @@ pub const File = struct { if (iovecs.len == 0) return @as(usize, 0); const first = iovecs[0]; return windows.ReadFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.preadv(self.handle, iovecs, offset); + } else { + return std.event.Loop.instance.?.preadv(self.handle, iovecs, offset, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index 6ed555011e..6fb9d4388b 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -622,12 +622,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdReadable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForReading, // can be a race condition EIO => return error.InputOutput, EISDIR => return error.IsDir, From 9075f8e5a1a788770cc8193d6f54118434e72a4b Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 19 Jun 2020 23:29:11 +0200 Subject: [PATCH 07/14] write Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 40 ++++++++++++++++++++++++++-------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index a14e798c50..ec45e85630 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -956,23 +956,35 @@ pub const Loop = struct { /// Performs an async `os.write` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn write(self: *Loop, fd: os.fd_t, bytes: []const u8) os.WriteError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .write = .{ - .fd = fd, - .bytes = bytes, - .result = undefined, + pub fn write(self: *Loop, fd: os.fd_t, bytes: []const u8, simulate_evented: bool) os.WriteError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .write = .{ + .fd = fd, + .bytes = bytes, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.write.result; + } else { + while (true) { + return os.write(fd, bytes) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdWritable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.write.result; } /// Performs an async `os.writev` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 4aa33fc5b9..428b758e61 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -547,10 +547,12 @@ pub const File = struct { pub fn write(self: File, bytes: []const u8) WriteError!usize { if (is_windows) { return windows.WriteFile(self.handle, bytes, null, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.write(self.handle, bytes); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.write(self.handle, bytes); + } else { + return std.event.Loop.instance.?.write(self.handle, bytes, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index 6fb9d4388b..da5ce13508 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -721,12 +721,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdWritable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForWriting, // can be a race condition. EDESTADDRREQ => unreachable, // `connect` was never called. EDQUOT => return error.DiskQuota, From 18f6629bd8ad8bd13108ddce82c32baf6f53628e Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 19 Jun 2020 23:34:02 +0200 Subject: [PATCH 08/14] writev Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 40 ++++++++++++++++++++++++++-------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index ec45e85630..e5fdbd2e3a 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -989,23 +989,35 @@ pub const Loop = struct { /// Performs an async `os.writev` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn writev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const) os.WriteError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .writev = .{ - .fd = fd, - .iov = iov, - .result = undefined, + pub fn writev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, simulate_evented: bool) os.WriteError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .writev = .{ + .fd = fd, + .iov = iov, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.writev.result; + } else { + while (true) { + return os.writev(fd, iov) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdWritable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.writev.result; } /// Performs an async `os.pwritev` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 428b758e61..ab7ea2f579 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -586,10 +586,12 @@ pub const File = struct { if (iovecs.len == 0) return @as(usize, 0); const first = iovecs[0]; return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], null, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.writev(self.handle, iovecs); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.writev(self.handle, iovecs); + } else { + return std.event.Loop.instance.?.writev(self.handle, iovecs, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index da5ce13508..8f761b48be 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -789,12 +789,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdWritable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForWriting, // Can be a race condition. EDESTADDRREQ => unreachable, // `connect` was never called. EDQUOT => return error.DiskQuota, From 7a07c62a075ada32c5eca298e4ed6a4c8a14cf89 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Sat, 20 Jun 2020 00:17:10 +0200 Subject: [PATCH 09/14] pwrite Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 49 +++++++++++++++++++++++++++++++++++++++++- lib/std/fs/file.zig | 8 ++++--- lib/std/os.zig | 7 +----- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index e5fdbd2e3a..b3b62bbe8e 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -1020,9 +1020,43 @@ pub const Loop = struct { } } + /// Performs an async `os.pwrite` using a separate thread. + /// `fd` must block and not return EAGAIN. + pub fn pwrite(self: *Loop, fd: os.fd_t, bytes: []const u8, offset: u64, simulate_evented: bool) os.PWriteError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .pwrite = .{ + .fd = fd, + .bytes = bytes, + .offset = offset, + .result = undefined, + }, + }, + .finish = .{ .TickNode = .{ .data = @frame() } }, + }, + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.pwrite.result; + } else { + while (true) { + return os.pwrite(fd, bytes, offset) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdWritable(fd); + continue; + }, + else => return err, + }; + } + } + } + /// Performs an async `os.pwritev` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64) os.WriteError!usize { + pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64) os.PWriteError!usize { var req_node = Request.Node{ .data = .{ .msg = .{ @@ -1194,6 +1228,9 @@ pub const Loop = struct { .writev => |*msg| { msg.result = os.writev(msg.fd, msg.iov); }, + .pwrite => |*msg| { + msg.result = os.pwrite(msg.fd, msg.bytes, msg.offset); + }, .pwritev => |*msg| { msg.result = os.pwritev(msg.fd, msg.iov, msg.offset); }, @@ -1263,6 +1300,7 @@ pub const Loop = struct { readv: ReadV, write: Write, writev: WriteV, + pwrite: PWrite, pwritev: PWriteV, pread: PRead, preadv: PReadV, @@ -1306,6 +1344,15 @@ pub const Loop = struct { pub const Error = os.WriteError; }; + pub const PWrite = struct { + fd: os.fd_t, + bytes: []const u8, + offset: usize, + result: Error!usize, + + pub const Error = os.PWriteError; + }; + pub const PWriteV = struct { fd: os.fd_t, iov: []const os.iovec_const, diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index ab7ea2f579..60efe28ec2 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -566,10 +566,12 @@ pub const File = struct { pub fn pwrite(self: File, bytes: []const u8, offset: u64) PWriteError!usize { if (is_windows) { return windows.WriteFile(self.handle, bytes, offset, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.pwrite(self.handle, bytes, offset); + } else { + return std.event.Loop.instance.?.pwrite(self.handle, bytes, offset, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index 8f761b48be..595815a1e7 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -875,12 +875,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdWritable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForWriting, // Can be a race condition. EDESTADDRREQ => unreachable, // `connect` was never called. EDQUOT => return error.DiskQuota, From 7fec5b3def36bc73e9e48a777bcca838c4b86770 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Sat, 20 Jun 2020 00:19:38 +0200 Subject: [PATCH 10/14] pwritev Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 44 +++++++++++++++++++++++++++--------------- lib/std/fs/file.zig | 8 +++++--- lib/std/os.zig | 7 +------ 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index b3b62bbe8e..ae2d2f1499 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -1022,7 +1022,7 @@ pub const Loop = struct { /// Performs an async `os.pwrite` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn pwrite(self: *Loop, fd: os.fd_t, bytes: []const u8, offset: u64, simulate_evented: bool) os.PWriteError!usize { + pub fn pwrite(self: *Loop, fd: os.fd_t, bytes: []const u8, offset: u64, simulate_evented: bool) os.PerformsWriteError!usize { if (simulate_evented) { var req_node = Request.Node{ .data = .{ @@ -1056,24 +1056,36 @@ pub const Loop = struct { /// Performs an async `os.pwritev` using a separate thread. /// `fd` must block and not return EAGAIN. - pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64) os.PWriteError!usize { - var req_node = Request.Node{ - .data = .{ - .msg = .{ - .pwritev = .{ - .fd = fd, - .iov = iov, - .offset = offset, - .result = undefined, + pub fn pwritev(self: *Loop, fd: os.fd_t, iov: []const os.iovec_const, offset: u64, simulate_evented: bool) os.PWriteError!usize { + if (simulate_evented) { + var req_node = Request.Node{ + .data = .{ + .msg = .{ + .pwritev = .{ + .fd = fd, + .iov = iov, + .offset = offset, + .result = undefined, + }, }, + .finish = .{ .TickNode = .{ .data = @frame() } }, }, - .finish = .{ .TickNode = .{ .data = @frame() } }, - }, - }; - suspend { - self.posixFsRequest(&req_node); + }; + suspend { + self.posixFsRequest(&req_node); + } + return req_node.data.msg.pwritev.result; + } else { + while (true) { + return os.pwritev(fd, iov, offset) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdWritable(fd); + continue; + }, + else => return err, + }; + } } - return req_node.data.msg.pwritev.result; } /// Performs an async `os.faccessatZ` using a separate thread. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 60efe28ec2..f3e980b9f0 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -621,10 +621,12 @@ pub const File = struct { if (iovecs.len == 0) return @as(usize, 0); const first = iovecs[0]; return windows.WriteFile(self.handle, first.iov_base[0..first.iov_len], offset, self.intended_io_mode); - } else if (self.capable_io_mode != self.intended_io_mode) { - return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset); - } else { + } + + if (self.intended_io_mode == .blocking) { return os.pwritev(self.handle, iovecs, offset); + } else { + return std.event.Loop.instance.?.pwritev(self.handle, iovecs, offset, self.capable_io_mode != self.intended_io_mode); } } diff --git a/lib/std/os.zig b/lib/std/os.zig index 595815a1e7..1138013e8c 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -958,12 +958,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz EINTR => continue, EINVAL => unreachable, EFAULT => unreachable, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdWritable(fd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EBADF => return error.NotOpenForWriting, // Can be a race condition. EDESTADDRREQ => unreachable, // `connect` was never called. EDQUOT => return error.DiskQuota, From 419aea54cb30b394191778fcc70effaf5181bf33 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Sat, 20 Jun 2020 00:35:08 +0200 Subject: [PATCH 11/14] sendto Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 21 +++++++++++++++++++++ lib/std/net.zig | 12 ++++++++++-- lib/std/os.zig | 8 +------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index ae2d2f1499..3a79d36a10 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -1088,6 +1088,27 @@ pub const Loop = struct { } } + pub fn sendto( + self: *Loop, + /// The file descriptor of the sending socket. + sockfd: os.fd_t, + /// Message to send. + buf: []const u8, + flags: u32, + dest_addr: ?*const os.sockaddr, + addrlen: os.socklen_t, + ) os.SendError!usize { + while (true) { + return os.sendto(sockfd, buf, flags, dest_addr, addrlen) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdWritable(sockfd); + continue; + }, + else => return err, + }; + } + } + /// Performs an async `os.faccessatZ` using a separate thread. /// `fd` must block and not return EAGAIN. pub fn faccessatZ( diff --git a/lib/std/net.zig b/lib/std/net.zig index 928ebbbce5..8fe19f955d 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -1435,7 +1435,11 @@ fn resMSendRc( if (answers[i].len == 0) { var j: usize = 0; while (j < ns.len) : (j += 1) { - _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; + if (std.io.is_async) { + _ = std.event.Loop.instance.?.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; + } else { + _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; + } } } } @@ -1476,7 +1480,11 @@ fn resMSendRc( 0, 3 => {}, 2 => if (servfail_retry != 0) { servfail_retry -= 1; - _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; + if (std.io.is_async) { + _ = std.event.Loop.instance.?.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; + } else { + _ = os.sendto(fd, queries[i], os.MSG_NOSIGNAL, &ns[j].any, sl) catch undefined; + } }, else => continue, } diff --git a/lib/std/os.zig b/lib/std/os.zig index 1138013e8c..2f354e33d6 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -4571,14 +4571,8 @@ pub fn sendto( const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen); switch (errno(rc)) { 0 => return @intCast(usize, rc), - EACCES => return error.AccessDenied, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdWritable(sockfd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, EALREADY => return error.FastOpenAlreadyInProgress, EBADF => unreachable, // always a race condition ECONNRESET => return error.ConnectionResetByPeer, From c196c27af86f0f10b2f53240a68477391c4b9820 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Sat, 20 Jun 2020 00:45:51 +0200 Subject: [PATCH 12/14] recvfrom Signed-off-by: Loris Cro --- lib/std/event/loop.zig | 18 ++++++++++++++++++ lib/std/net.zig | 5 ++++- lib/std/os.zig | 7 +------ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 3a79d36a10..c3bf2495ff 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -1109,6 +1109,24 @@ pub const Loop = struct { } } + pub fn recvfrom( + sockfd: os.fd_t, + buf: []u8, + flags: u32, + src_addr: ?*os.sockaddr, + addrlen: ?*os.socklen_t, + ) os.RecvFromError!usize { + while (true) { + return os.recvfrom(sockfd, buf, flags, src_addr, addrlen) catch |err| switch (err) { + error.WouldBlock => { + self.waitUntilFdReadable(sockfd); + continue; + }, + else => return err, + }; + } + } + /// Performs an async `os.faccessatZ` using a separate thread. /// `fd` must block and not return EAGAIN. pub fn faccessatZ( diff --git a/lib/std/net.zig b/lib/std/net.zig index 8fe19f955d..fe7d0fafe6 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -1454,7 +1454,10 @@ fn resMSendRc( while (true) { var sl_copy = sl; - const rlen = os.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break; + const rlen = if (std.io.is_async) + std.event.Loop.instance.?.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break + else + os.recvfrom(fd, answer_bufs[next], 0, &sa.any, &sl_copy) catch break; // Ignore non-identifiable packets if (rlen < 4) continue; diff --git a/lib/std/os.zig b/lib/std/os.zig index 2f354e33d6..2c5f3065b2 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -5068,12 +5068,7 @@ pub fn recvfrom( ENOTCONN => unreachable, ENOTSOCK => unreachable, EINTR => continue, - EAGAIN => if (std.event.Loop.instance) |loop| { - loop.waitUntilFdReadable(sockfd); - continue; - } else { - return error.WouldBlock; - }, + EAGAIN => return error.WouldBlock, ENOMEM => return error.SystemResources, ECONNREFUSED => return error.ConnectionRefused, else => |err| return unexpectedErrno(err), From 8d01133bd04423f896dee81b89c56372aa1ee310 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 25 Sep 2020 18:42:24 +0200 Subject: [PATCH 13/14] update doc comments Signed-off-by: Loris Cro --- lib/std/os.zig | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 2c5f3065b2..c06ce4ed00 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -314,8 +314,8 @@ pub const ReadError = error{ /// Returns the number of bytes that were read, which can be less than /// buf.len. If 0 bytes were read, that means EOF. -/// If the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in error.WouldBlock. +/// If `fd` is opened in non blocking mode, the function will return error.WouldBlock +/// when EAGAIN is received. /// /// Linux has a limit on how many bytes may be transferred in one `read` call, which is `0x7ffff000` /// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as @@ -382,8 +382,8 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { /// Number of bytes read is returned. Upon reading end-of-file, zero is returned. /// -/// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// For POSIX systems, if `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. /// @@ -440,8 +440,8 @@ pub const PReadError = ReadError || error{Unseekable}; /// /// Retries when interrupted by a signal. /// -/// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// For POSIX systems, if `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { @@ -571,8 +571,8 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { /// /// Retries when interrupted by a signal. /// -/// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// For POSIX systems, if `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. /// @@ -667,8 +667,8 @@ pub const WriteError = error{ /// another write() call to transfer the remaining bytes. The subsequent call will either /// transfer further bytes or may result in an error (e.g., if the disk is now full). /// -/// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// For POSIX systems, if `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. /// @@ -747,8 +747,8 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { /// another write() call to transfer the remaining bytes. The subsequent call will either /// transfer further bytes or may result in an error (e.g., if the disk is now full). /// -/// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// For POSIX systems, if `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received.k`. /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. /// @@ -817,8 +817,8 @@ pub const PWriteError = WriteError || error{Unseekable}; /// another write() call to transfer the remaining bytes. The subsequent call will either /// transfer further bytes or may result in an error (e.g., if the disk is now full). /// -/// For POSIX systems, if the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// For POSIX systems, if `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. /// @@ -904,8 +904,8 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { /// another write() call to transfer the remaining bytes. The subsequent call will either /// transfer further bytes or may result in an error (e.g., if the disk is now full). /// -/// If the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in `error.WouldBlock`. +/// If `fd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. /// /// The following systems do not have this syscall, and will return partial writes if more than one /// vector is provided: @@ -2806,8 +2806,8 @@ pub const AcceptError = error{ } || UnexpectedError; /// Accept a connection on a socket. -/// If the application has a global event loop enabled, EAGAIN is handled -/// via the event loop. Otherwise EAGAIN results in error.WouldBlock. +/// If `sockfd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. pub fn accept( /// This argument is a socket that has been created with `socket`, bound to a local address /// with `bind`, and is listening for connections after a `listen`. @@ -3036,6 +3036,8 @@ pub const ConnectError = error{ } || UnexpectedError; /// Initiate a connection on a socket. +/// If `sockfd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN or EINPROGRESS is received. pub fn connect(sockfd: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void { if (builtin.os.tag == .windows) { const rc = windows.ws2_32.connect(sockfd, sock_addr, len); @@ -5051,6 +5053,8 @@ pub const RecvFromError = error{ SystemResources, } || UnexpectedError; +/// If `sockfd` is opened in non blocking mode, the function will +/// return error.WouldBlock when EAGAIN is received. pub fn recvfrom( sockfd: fd_t, buf: []u8, From dc01ef738828a4eba08e95eaaf89442ca2f3e2f8 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Fri, 25 Sep 2020 23:21:20 +0200 Subject: [PATCH 14/14] Remove noop check Co-authored-by: Andrew Kelley --- lib/std/fs/file.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index f3e980b9f0..8d4f5df2e8 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -416,7 +416,7 @@ pub const File = struct { return windows.ReadFile(self.handle, buffer, null, self.intended_io_mode); } - if (self.intended_io_mode == .blocking or !std.io.is_async) { + if (self.intended_io_mode == .blocking) { return os.read(self.handle, buffer); } else { return std.event.Loop.instance.?.read(self.handle, buffer, self.capable_io_mode != self.intended_io_mode);