Commit be1ae430a1
Changed files (3)
lib
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,
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),
}
}
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,