diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 345d9728e3..fa3c63d609 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -1988,7 +1988,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: Io.net.Socket.Handle) Io.net fn netReadPosix(userdata: ?*anyopaque, stream: Io.net.Stream, data: [][]u8) Io.net.Stream.Reader.Error!usize { const pool: *Pool = @ptrCast(@alignCast(userdata)); - try pool.checkCancel(); + const fd = stream.socket.handle; var iovecs_buffer: [max_iovecs_len]posix.iovec = undefined; var i: usize = 0; @@ -2001,9 +2001,54 @@ fn netReadPosix(userdata: ?*anyopaque, stream: Io.net.Stream, data: [][]u8) Io.n } const dest = iovecs_buffer[0..i]; assert(dest[0].len > 0); - const n = try posix.readv(stream.socket.handle, dest); - if (n == 0) return error.EndOfStream; - return n; + + if (native_os == .wasi and !builtin.link_libc) while (true) { + try pool.checkCancel(); + var n: usize = undefined; + switch (std.os.wasi.fd_read(fd, dest.ptr, dest.len, &n)) { + .SUCCESS => { + if (n == 0) return error.EndOfStream; + return n; + }, + .INTR => continue, + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.ConnectionTimedOut, + .NOTCAPABLE => return error.AccessDenied, + else => |err| return posix.unexpectedErrno(err), + } + }; + + while (true) { + try pool.checkCancel(); + const rc = posix.system.readv(fd, dest.ptr, @intCast(dest.len)); + switch (posix.errno(rc)) { + .SUCCESS => { + const n: usize = @intCast(rc); + if (n == 0) return error.EndOfStream; + return n; + }, + .INTR => continue, + .INVAL => |err| return errnoBug(err), + .FAULT => |err| return errnoBug(err), + .AGAIN => |err| return errnoBug(err), + .BADF => |err| return errnoBug(err), // Always a race condition. + .NOBUFS => return error.SystemResources, + .NOMEM => return error.SystemResources, + .NOTCONN => return error.SocketUnconnected, + .CONNRESET => return error.ConnectionResetByPeer, + .TIMEDOUT => return error.ConnectionTimedOut, + .PIPE => return error.BrokenPipe, + .NETDOWN => return error.NetworkDown, + else => |err| return posix.unexpectedErrno(err), + } + } } const have_sendmmsg = builtin.os.tag == .linux; @@ -2071,7 +2116,7 @@ fn netSendOne( .WSAEHOSTUNREACH => return error.NetworkUnreachable, // TODO: WSAEINPROGRESS, WSAEINTR .WSAEINVAL => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENETRESET => return error.ConnectionResetByPeer, .WSAENETUNREACH => return error.NetworkUnreachable, .WSAENOTCONN => return error.SocketUnconnected, @@ -2114,7 +2159,7 @@ fn netSendOne( .HOSTUNREACH => return error.NetworkUnreachable, .NETUNREACH => return error.NetworkUnreachable, .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkSubsystemFailed, + .NETDOWN => return error.NetworkDown, else => |err| return posix.unexpectedErrno(err), } } diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index fe2f7e9973..d76a7a9b34 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -1087,13 +1087,18 @@ pub const Stream = struct { stream: Stream, err: ?Error, - pub const Error = std.posix.ReadError || error{ - SocketNotBound, - MessageTooBig, - NetworkSubsystemFailed, + pub const Error = error{ + SystemResources, + BrokenPipe, ConnectionResetByPeer, + ConnectionTimedOut, SocketUnconnected, - } || Io.Cancelable || Io.Writer.Error || error{EndOfStream}; + /// The file descriptor does not hold the required rights to read + /// from it. + AccessDenied, + NetworkDown, + EndOfStream, + } || Io.Cancelable || Io.UnexpectedError; pub fn init(stream: Stream, io: Io, buffer: []u8) Reader { return .{ @@ -1140,7 +1145,7 @@ pub const Stream = struct { ConnectionResetByPeer, SocketNotBound, MessageTooBig, - NetworkSubsystemFailed, + NetworkDown, SystemResources, SocketUnconnected, Unexpected, diff --git a/lib/std/posix.zig b/lib/std/posix.zig index eebff5479d..47ca1e080c 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -3613,7 +3613,7 @@ pub const ShutdownError = error{ BlockingOperationInProgress, /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, /// The socket is not connected (connection-oriented sockets only). SocketUnconnected, @@ -3635,7 +3635,7 @@ pub fn shutdown(sock: socket_t, how: ShutdownHow) ShutdownError!void { .WSAECONNRESET => return error.ConnectionResetByPeer, .WSAEINPROGRESS => return error.BlockingOperationInProgress, .WSAEINVAL => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENOTCONN => return error.SocketUnconnected, .WSAENOTSOCK => unreachable, .WSANOTINITIALISED => unreachable, @@ -3697,7 +3697,7 @@ pub const BindError = error{ ReadOnlyFileSystem, /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, FileDescriptorNotASocket, @@ -3718,7 +3718,7 @@ pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!voi .WSAEFAULT => unreachable, // invalid pointers .WSAEINVAL => return error.AlreadyBound, .WSAENOBUFS => return error.SystemResources, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, else => |err| return windows.unexpectedWSAError(err), } unreachable; @@ -3763,7 +3763,7 @@ pub const ListenError = error{ OperationNotSupported, /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, /// Ran out of system resources /// On Windows it can either run out of socket descriptors or buffer space @@ -3782,7 +3782,7 @@ pub fn listen(sock: socket_t, backlog: u31) ListenError!void { if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, // not initialized WSA - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAEADDRINUSE => return error.AddressInUse, .WSAEISCONN => return error.AlreadyConnected, .WSAEINVAL => return error.SocketNotBound, @@ -3840,7 +3840,7 @@ pub const AcceptError = error{ ConnectionResetByPeer, /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, /// The referenced socket is not a type that supports connection-oriented service. OperationNotSupported, @@ -3893,7 +3893,7 @@ pub fn accept( .WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAEINVAL => return error.SocketNotListening, .WSAEMFILE => return error.ProcessFdQuotaExceeded, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENOBUFS => return error.FileDescriptorNotASocket, .WSAEOPNOTSUPP => return error.OperationNotSupported, .WSAEWOULDBLOCK => return error.WouldBlock, @@ -3964,7 +3964,7 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { if (windows.ws2_32.ioctlsocket(sock, windows.ws2_32.FIONBIO, &mode) == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENOTSOCK => return error.FileDescriptorNotASocket, // TODO: handle more errors else => |err| return windows.unexpectedWSAError(err), @@ -4105,7 +4105,7 @@ pub const GetSockNameError = error{ SystemResources, /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, /// Socket hasn't been bound yet SocketNotBound, @@ -4119,7 +4119,7 @@ pub fn getsockname(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAEFAULT => unreachable, // addr or addrlen have invalid pointers or addrlen points to an incorrect value .WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAEINVAL => return error.SocketNotBound, @@ -4148,7 +4148,7 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAEFAULT => unreachable, // addr or addrlen have invalid pointers or addrlen points to an incorrect value .WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAEINVAL => return error.SocketNotBound, @@ -6057,7 +6057,7 @@ pub const SendError = error{ NetworkUnreachable, /// The local network interface used to reach the destination is down. - NetworkSubsystemFailed, + NetworkDown, /// The destination address is not listening. ConnectionRefused, @@ -6106,7 +6106,7 @@ pub fn sendmsg( .WSAEHOSTUNREACH => return error.NetworkUnreachable, // TODO: WSAEINPROGRESS, WSAEINTR .WSAEINVAL => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENETRESET => return error.ConnectionResetByPeer, .WSAENETUNREACH => return error.NetworkUnreachable, .WSAENOTCONN => return error.SocketUnconnected, @@ -6146,7 +6146,7 @@ pub fn sendmsg( .HOSTUNREACH => return error.NetworkUnreachable, .NETUNREACH => return error.NetworkUnreachable, .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkSubsystemFailed, + .NETDOWN => return error.NetworkDown, else => |err| return unexpectedErrno(err), } } @@ -6209,7 +6209,7 @@ pub fn sendto( .WSAEHOSTUNREACH => return error.NetworkUnreachable, // TODO: WSAEINPROGRESS, WSAEINTR .WSAEINVAL => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENETRESET => return error.ConnectionResetByPeer, .WSAENETUNREACH => return error.NetworkUnreachable, .WSAENOTCONN => return error.SocketUnconnected, @@ -6251,7 +6251,7 @@ pub fn sendto( .HOSTUNREACH => return error.NetworkUnreachable, .NETUNREACH => return error.NetworkUnreachable, .NOTCONN => return error.SocketUnconnected, - .NETDOWN => return error.NetworkSubsystemFailed, + .NETDOWN => return error.NetworkDown, else => |err| return unexpectedErrno(err), } } @@ -6390,7 +6390,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len pub const PollError = error{ /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, /// The kernel had no space to allocate file descriptor tables. SystemResources, @@ -6401,7 +6401,7 @@ pub fn poll(fds: []pollfd, timeout: i32) PollError!usize { switch (windows.poll(fds.ptr, @intCast(fds.len), timeout)) { windows.ws2_32.SOCKET_ERROR => switch (windows.ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENOBUFS => return error.SystemResources, // TODO: handle more errors else => |err| return windows.unexpectedWSAError(err), @@ -6473,7 +6473,7 @@ pub const RecvFromError = error{ MessageTooBig, /// The network subsystem has failed. - NetworkSubsystemFailed, + NetworkDown, /// The socket is not connected (connection-oriented sockets only). SocketUnconnected, @@ -6504,7 +6504,7 @@ pub fn recvfrom( .WSAECONNRESET => return error.ConnectionResetByPeer, .WSAEINVAL => return error.SocketNotBound, .WSAEMSGSIZE => return error.MessageTooBig, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAENOTCONN => return error.SocketUnconnected, .WSAEWOULDBLOCK => return error.WouldBlock, .WSAETIMEDOUT => return error.ConnectionTimedOut, @@ -6578,7 +6578,7 @@ pub fn recvmsg( .PIPE => return error.BrokenPipe, .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. .CONNRESET => return error.ConnectionResetByPeer, - .NETDOWN => return error.NetworkSubsystemFailed, + .NETDOWN => return error.NetworkDown, else => |err| return unexpectedErrno(err), } } @@ -6601,7 +6601,7 @@ pub const SetSockOptError = error{ PermissionDenied, OperationNotSupported, - NetworkSubsystemFailed, + NetworkDown, FileDescriptorNotASocket, SocketNotBound, NoDevice, @@ -6614,7 +6614,7 @@ pub fn setsockopt(fd: socket_t, level: i32, optname: u32, opt: []const u8) SetSo if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, - .WSAENETDOWN => return error.NetworkSubsystemFailed, + .WSAENETDOWN => return error.NetworkDown, .WSAEFAULT => unreachable, .WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAEINVAL => return error.SocketNotBound,