Commit e85c89630e
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{
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,
}
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,