aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-01-23 23:00:15 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-01-23 23:00:15 -0800
commitde0cf421115ed3814ccc4d46e4d6202aac792ba0 (patch)
tree8c3f609e9497c30ae2f7512a5b5d7b8e0d37595f
parentec9e4eb97e0633e508606af9d18e76a3c63647da (diff)
downloadbun-de0cf421115ed3814ccc4d46e4d6202aac792ba0.tar.gz
bun-de0cf421115ed3814ccc4d46e4d6202aac792ba0.tar.zst
bun-de0cf421115ed3814ccc4d46e4d6202aac792ba0.zip
Use non-cancellable syscalls for HTTP & use errno for errors
-rw-r--r--src/http_client_async.zig6
-rw-r--r--src/io/io_darwin.zig532
-rw-r--r--src/io/io_linux.zig473
3 files changed, 933 insertions, 78 deletions
diff --git a/src/http_client_async.zig b/src/http_client_async.zig
index d0ab75fab..21bc183be 100644
--- a/src/http_client_async.zig
+++ b/src/http_client_async.zig
@@ -588,7 +588,11 @@ const AsyncSocket = struct {
connect_completion: AsyncIO.Completion = undefined,
close_completion: AsyncIO.Completion = undefined,
- const ConnectError = AsyncIO.ConnectError || std.os.SocketError || std.os.SetSockOptError || error{UnknownHostName};
+ const ConnectError = AsyncIO.ConnectError || std.os.SocketError || std.os.SetSockOptError || error{
+ UnknownHostName,
+ ConnectionRefused,
+ AddressNotAvailable,
+ };
pub fn init(io: *AsyncIO, socket: std.os.socket_t, allocator: std.mem.Allocator) !AsyncSocket {
var head = AsyncMessage.get(allocator);
diff --git a/src/io/io_darwin.zig b/src/io/io_darwin.zig
index c072cd4bd..97ccd6d23 100644
--- a/src/io/io_darwin.zig
+++ b/src/io/io_darwin.zig
@@ -15,9 +15,383 @@ const os = struct {
pub const EOVERFLOW = 84;
pub const ESPIPE = 29;
};
+
+const SystemErrno = @import("../darwin_c.zig").SystemErrno;
+pub const Errno = error{
+ EPERM,
+ ENOENT,
+ ESRCH,
+ EINTR,
+ EIO,
+ ENXIO,
+ E2BIG,
+ ENOEXEC,
+ EBADF,
+ ECHILD,
+ EDEADLK,
+ ENOMEM,
+ EACCES,
+ EFAULT,
+ ENOTBLK,
+ EBUSY,
+ EEXIST,
+ EXDEV,
+ ENODEV,
+ ENOTDIR,
+ EISDIR,
+ EINVAL,
+ ENFILE,
+ EMFILE,
+ ENOTTY,
+ ETXTBSY,
+ EFBIG,
+ ENOSPC,
+ ESPIPE,
+ EROFS,
+ EMLINK,
+ EPIPE,
+ EDOM,
+ ERANGE,
+ EAGAIN,
+ EINPROGRESS,
+ EALREADY,
+ ENOTSOCK,
+ EDESTADDRREQ,
+ EMSGSIZE,
+ EPROTOTYPE,
+ ENOPROTOOPT,
+ EPROTONOSUPPORT,
+ ESOCKTNOSUPPORT,
+ ENOTSUP,
+ EPFNOSUPPORT,
+ EAFNOSUPPORT,
+ EADDRINUSE,
+ EADDRNOTAVAIL,
+ ENETDOWN,
+ ENETUNREACH,
+ ENETRESET,
+ ECONNABORTED,
+ ECONNRESET,
+ ENOBUFS,
+ EISCONN,
+ ENOTCONN,
+ ESHUTDOWN,
+ ETOOMANYREFS,
+ ETIMEDOUT,
+ ECONNREFUSED,
+ ELOOP,
+ ENAMETOOLONG,
+ EHOSTDOWN,
+ EHOSTUNREACH,
+ ENOTEMPTY,
+ EPROCLIM,
+ EUSERS,
+ EDQUOT,
+ ESTALE,
+ EREMOTE,
+ EBADRPC,
+ ERPCMISMATCH,
+ EPROGUNAVAIL,
+ EPROGMISMATCH,
+ EPROCUNAVAIL,
+ ENOLCK,
+ ENOSYS,
+ EFTYPE,
+ EAUTH,
+ ENEEDAUTH,
+ EPWROFF,
+ EDEVERR,
+ EOVERFLOW,
+ EBADEXEC,
+ EBADARCH,
+ ESHLIBVERS,
+ EBADMACHO,
+ ECANCELED,
+ EIDRM,
+ ENOMSG,
+ EILSEQ,
+ ENOATTR,
+ EBADMSG,
+ EMULTIHOP,
+ ENODATA,
+ ENOLINK,
+ ENOSR,
+ ENOSTR,
+ EPROTO,
+ ETIME,
+ EOPNOTSUPP,
+ ENOPOLICY,
+ ENOTRECOVERABLE,
+ EOWNERDEAD,
+ EQFULL,
+ Unexpected,
+};
+
+const errno_map: [108]Errno = brk: {
+ var errors: [108]Errno = undefined;
+ errors[1] = error.EPERM;
+ errors[2] = error.ENOENT;
+ errors[3] = error.ESRCH;
+ errors[4] = error.EINTR;
+ errors[5] = error.EIO;
+ errors[6] = error.ENXIO;
+ errors[7] = error.E2BIG;
+ errors[8] = error.ENOEXEC;
+ errors[9] = error.EBADF;
+ errors[10] = error.ECHILD;
+ errors[11] = error.EDEADLK;
+ errors[12] = error.ENOMEM;
+ errors[13] = error.EACCES;
+ errors[14] = error.EFAULT;
+ errors[15] = error.ENOTBLK;
+ errors[16] = error.EBUSY;
+ errors[17] = error.EEXIST;
+ errors[18] = error.EXDEV;
+ errors[19] = error.ENODEV;
+ errors[20] = error.ENOTDIR;
+ errors[21] = error.EISDIR;
+ errors[22] = error.EINVAL;
+ errors[23] = error.ENFILE;
+ errors[24] = error.EMFILE;
+ errors[25] = error.ENOTTY;
+ errors[26] = error.ETXTBSY;
+ errors[27] = error.EFBIG;
+ errors[28] = error.ENOSPC;
+ errors[29] = error.ESPIPE;
+ errors[30] = error.EROFS;
+ errors[31] = error.EMLINK;
+ errors[32] = error.EPIPE;
+ errors[33] = error.EDOM;
+ errors[34] = error.ERANGE;
+ errors[35] = error.EAGAIN;
+ errors[36] = error.EINPROGRESS;
+ errors[37] = error.EALREADY;
+ errors[38] = error.ENOTSOCK;
+ errors[39] = error.EDESTADDRREQ;
+ errors[40] = error.EMSGSIZE;
+ errors[41] = error.EPROTOTYPE;
+ errors[42] = error.ENOPROTOOPT;
+ errors[43] = error.EPROTONOSUPPORT;
+ errors[44] = error.ESOCKTNOSUPPORT;
+ errors[45] = error.ENOTSUP;
+ errors[46] = error.EPFNOSUPPORT;
+ errors[47] = error.EAFNOSUPPORT;
+ errors[48] = error.EADDRINUSE;
+ errors[49] = error.EADDRNOTAVAIL;
+ errors[50] = error.ENETDOWN;
+ errors[51] = error.ENETUNREACH;
+ errors[52] = error.ENETRESET;
+ errors[53] = error.ECONNABORTED;
+ errors[54] = error.ECONNRESET;
+ errors[55] = error.ENOBUFS;
+ errors[56] = error.EISCONN;
+ errors[57] = error.ENOTCONN;
+ errors[58] = error.ESHUTDOWN;
+ errors[59] = error.ETOOMANYREFS;
+ errors[60] = error.ETIMEDOUT;
+ errors[61] = error.ECONNREFUSED;
+ errors[62] = error.ELOOP;
+ errors[63] = error.ENAMETOOLONG;
+ errors[64] = error.EHOSTDOWN;
+ errors[65] = error.EHOSTUNREACH;
+ errors[66] = error.ENOTEMPTY;
+ errors[67] = error.EPROCLIM;
+ errors[68] = error.EUSERS;
+ errors[69] = error.EDQUOT;
+ errors[70] = error.ESTALE;
+ errors[71] = error.EREMOTE;
+ errors[72] = error.EBADRPC;
+ errors[73] = error.ERPCMISMATCH;
+ errors[74] = error.EPROGUNAVAIL;
+ errors[75] = error.EPROGMISMATCH;
+ errors[76] = error.EPROCUNAVAIL;
+ errors[77] = error.ENOLCK;
+ errors[78] = error.ENOSYS;
+ errors[79] = error.EFTYPE;
+ errors[80] = error.EAUTH;
+ errors[81] = error.ENEEDAUTH;
+ errors[82] = error.EPWROFF;
+ errors[83] = error.EDEVERR;
+ errors[84] = error.EOVERFLOW;
+ errors[85] = error.EBADEXEC;
+ errors[86] = error.EBADARCH;
+ errors[87] = error.ESHLIBVERS;
+ errors[88] = error.EBADMACHO;
+ errors[89] = error.ECANCELED;
+ errors[90] = error.EIDRM;
+ errors[91] = error.ENOMSG;
+ errors[92] = error.EILSEQ;
+ errors[93] = error.ENOATTR;
+ errors[94] = error.EBADMSG;
+ errors[95] = error.EMULTIHOP;
+ errors[96] = error.ENODATA;
+ errors[97] = error.ENOLINK;
+ errors[98] = error.ENOSR;
+ errors[99] = error.ENOSTR;
+ errors[100] = error.EPROTO;
+ errors[101] = error.ETIME;
+ errors[102] = error.EOPNOTSUPP;
+ errors[103] = error.ENOPOLICY;
+ errors[104] = error.ENOTRECOVERABLE;
+ errors[105] = error.EOWNERDEAD;
+ errors[106] = error.EQFULL;
+ break :brk errors;
+};
+
+const socket_t = os.socket_t;
+const sockaddr = darwin.sockaddr;
+const socklen_t = darwin.socklen_t;
+const system = darwin;
+
+pub fn asError(err: anytype) Errno {
+ return switch (@enumToInt(err)) {
+ 1...errno_map.len => |val| errno_map[@intCast(u8, val)],
+ else => error.Unexpected,
+ };
+}
+const fd_t = os.fd_t;
+
const mem = std.mem;
const assert = std.debug.assert;
const c = std.c;
+const darwin = struct {
+ pub usingnamespace os.darwin;
+ pub extern "c" fn @"recvfrom$NOCANCEL"(sockfd: c.fd_t, noalias buf: *anyopaque, len: usize, flags: u32, noalias src_addr: ?*c.sockaddr, noalias addrlen: ?*c.socklen_t) isize;
+ pub extern "c" fn @"sendto$NOCANCEL"(
+ sockfd: c.fd_t,
+ buf: *const anyopaque,
+ len: usize,
+ flags: u32,
+ dest_addr: ?*const c.sockaddr,
+ addrlen: c.socklen_t,
+ ) isize;
+ pub extern "c" fn @"fcntl$NOCANCEL"(fd: c.fd_t, cmd: c_int, ...) c_int;
+ pub extern "c" fn @"sendmsg$NOCANCEL"(sockfd: c.fd_t, msg: *const std.x.os.Socket.Message, flags: c_int) isize;
+ pub extern "c" fn @"recvmsg$NOCANCEL"(sockfd: c.fd_t, msg: *std.x.os.Socket.Message, flags: c_int) isize;
+ pub extern "c" fn @"connect$NOCANCEL"(sockfd: c.fd_t, sock_addr: *const c.sockaddr, addrlen: c.socklen_t) c_int;
+ pub extern "c" fn @"accept$NOCANCEL"(sockfd: c.fd_t, noalias addr: ?*c.sockaddr, noalias addrlen: ?*c.socklen_t) c_int;
+ pub extern "c" fn @"accept4$NOCANCEL"(sockfd: c.fd_t, noalias addr: ?*c.sockaddr, noalias addrlen: ?*c.socklen_t, flags: c_uint) c_int;
+};
+
+pub const Syscall = struct {
+ pub fn close(fd: std.os.fd_t) CloseError!void {
+ return switch (darwin.getErrno(darwin.@"close$NOCANCEL"(fd))) {
+ .SUCCESS => void{},
+ .BADF => error.FileDescriptorInvalid,
+ .IO => error.InputOutput,
+ else => |err| asError(err),
+ };
+ }
+
+ pub const SocketError = error{
+ /// Permission to create a socket of the specified type and/or
+ /// pro‐tocol is denied.
+ PermissionDenied,
+
+ /// The implementation does not support the specified address family.
+ AddressFamilyNotSupported,
+
+ /// Unknown protocol, or protocol family not available.
+ ProtocolFamilyNotAvailable,
+
+ /// The per-process limit on the number of open file descriptors has been reached.
+ ProcessFdQuotaExceeded,
+
+ /// The system-wide limit on the total number of open files has been reached.
+ SystemFdQuotaExceeded,
+
+ /// Insufficient memory is available. The socket cannot be created until sufficient
+ /// resources are freed.
+ SystemResources,
+
+ /// The protocol type or the specified protocol is not supported within this domain.
+ ProtocolNotSupported,
+
+ /// The socket type is not supported by the protocol.
+ SocketTypeNotSupported,
+ } || Errno;
+ const SOCK = os.SOCK;
+ const FD_CLOEXEC = os.FD_CLOEXEC;
+ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) Errno!usize {
+ const rc = darwin.@"fcntl$NOCANCEL"(fd, cmd, arg);
+ return switch (darwin.getErrno(rc)) {
+ .SUCCESS => @intCast(usize, rc),
+ else => |err| asError(err),
+ };
+ }
+
+ const F = std.os.F;
+ const O = std.os.O;
+ pub fn setSockFlags(sock: socket_t, flags: u32) !void {
+ if ((flags & SOCK.CLOEXEC) != 0) {
+ var fd_flags = try fcntl(sock, F.GETFD, 0);
+ fd_flags |= FD_CLOEXEC;
+ _ = try fcntl(sock, F.SETFD, fd_flags);
+ }
+
+ if ((flags & SOCK.NONBLOCK) != 0) {
+ var fl_flags = try fcntl(sock, F.GETFL, 0);
+ fl_flags |= O.NONBLOCK;
+ _ = try fcntl(sock, F.SETFL, fl_flags);
+ }
+ }
+
+ pub const SetSockOptError = error{
+ /// The socket is already connected, and a specified option cannot be set while the socket is connected.
+ AlreadyConnected,
+
+ /// The option is not supported by the protocol.
+ InvalidProtocolOption,
+
+ /// The send and receive timeout values are too big to fit into the timeout fields in the socket structure.
+ TimeoutTooBig,
+
+ /// Insufficient resources are available in the system to complete the call.
+ SystemResources,
+
+ // Setting the socket option requires more elevated permissions.
+ PermissionDenied,
+
+ NetworkSubsystemFailed,
+ FileDescriptorNotASocket,
+ SocketNotBound,
+ } || Errno;
+
+ pub fn setsockopt(fd: socket_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void {
+ switch (darwin.getErrno(darwin.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)))) {
+ .SUCCESS => {},
+ .DOM => return error.TimeoutTooBig,
+ .ISCONN => return error.AlreadyConnected,
+ .NOPROTOOPT => return error.InvalidProtocolOption,
+ .NOMEM => return error.SystemResources,
+ .NOBUFS => return error.SystemResources,
+ .PERM => return error.PermissionDenied,
+ else => |err| return asError(err),
+ }
+ }
+
+ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t {
+ const filtered_sock_type = socket_type & ~@as(u32, os.SOCK.NONBLOCK | os.SOCK.CLOEXEC);
+ const rc = darwin.socket(domain, filtered_sock_type, protocol);
+ switch (darwin.getErrno(rc)) {
+ .SUCCESS => {
+ const fd = @intCast(fd_t, rc);
+ try setSockFlags(fd, socket_type);
+ return fd;
+ },
+ .ACCES => return error.PermissionDenied,
+ .AFNOSUPPORT => return error.AddressFamilyNotSupported,
+ .INVAL => return error.ProtocolFamilyNotAvailable,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NOBUFS => return error.SystemResources,
+ .NOMEM => return error.SystemResources,
+ .PROTONOSUPPORT => return error.ProtocolNotSupported,
+ .PROTOTYPE => return error.SocketTypeNotSupported,
+ else => |err| return asError(err),
+ }
+ }
+};
const FIFO = @import("./fifo.zig").FIFO;
const Time = @import("./time.zig").Time;
@@ -217,7 +591,7 @@ fn flush_timeouts(self: *IO) ?u64 {
const timeout_ns = expires - now;
if (min_timeout) |min_ns| {
- min_timeout = std.math.min(min_ns, timeout_ns);
+ min_timeout = @minimum(min_ns, timeout_ns);
} else {
min_timeout = timeout_ns;
}
@@ -296,7 +670,7 @@ fn submit(
const result = OperationImpl.doOperation(op_data);
// Requeue onto io_pending if error.WouldBlock
- switch (operation_tag) {
+ switch (comptime operation_tag) {
.accept, .connect, .read, .write, .send, .recv => {
_ = result catch |err| switch (err) {
error.WouldBlock => {
@@ -423,11 +797,13 @@ pub fn accept(
null,
os.SOCK.NONBLOCK | os.SOCK.CLOEXEC,
);
- errdefer os.close(fd);
+ errdefer {
+ Syscall.close(fd) catch {};
+ }
// darwin doesn't support os.MSG.NOSIGNAL,
// but instead a socket option to avoid SIGPIPE.
- os.setsockopt(fd, os.SOL_SOCKET, os.SO_NOSIGPIPE, &mem.toBytes(@as(c_int, 1))) catch |err| return switch (err) {
+ Syscall.setsockopt(fd, os.SOL_SOCKET, os.SO_NOSIGPIPE, &mem.toBytes(@as(c_int, 1))) catch |err| return switch (err) {
error.TimeoutTooBig => unreachable,
error.PermissionDenied => error.NetworkSubsystemFailed,
error.AlreadyConnected => error.NetworkSubsystemFailed,
@@ -446,7 +822,7 @@ pub const CloseError = error{
DiskQuota,
InputOutput,
NoSpaceLeft,
-} || os.UnexpectedError;
+} || Errno;
pub fn close(
self: *IO,
@@ -470,19 +846,25 @@ pub fn close(
},
struct {
fn doOperation(op: anytype) CloseError!void {
- return switch (os.system.close(op.fd)) {
- 0 => {},
- os.EBADF => error.FileDescriptorInvalid,
- os.EINTR => {}, // A success, see https://github.com/ziglang/zig/issues/2425
- os.EIO => error.InputOutput,
- else => |errno| os.unexpectedErrno(os.errno(errno)),
- };
+ return Syscall.close(op.fd);
}
},
);
}
-pub const ConnectError = os.ConnectError;
+pub const ConnectError = error{
+ AddressFamilyNotSupported,
+ AddressInUse,
+ AddressNotAvailable,
+ ConnectionPending,
+ ConnectionRefused,
+ ConnectionResetByPeer,
+ ConnectionTimedOut,
+ NetworkUnreachable,
+ PermissionDenied,
+ SystemResources,
+ WouldBlock,
+} || Errno;
pub fn connect(
self: *IO,
@@ -491,7 +873,7 @@ pub fn connect(
comptime callback: fn (
context: Context,
completion: *Completion,
- result: ConnectError!void,
+ result: IO.ConnectError!void,
) void,
completion: *Completion,
socket: os.socket_t,
@@ -508,12 +890,53 @@ pub fn connect(
.initiated = false,
},
struct {
- fn doOperation(op: anytype) ConnectError!void {
+ fn doOperation(op: anytype) IO.ConnectError!void {
// Don't call connect after being rescheduled by io_pending as it gives EISCONN.
// Instead, check the socket error to see if has been connected successfully.
const result = switch (op.initiated) {
- true => os.getsockoptError(op.socket),
- else => os.connect(op.socket, &op.address.any, op.address.getOsSockLen()),
+ true => brk: {
+ var err_code: i32 = undefined;
+ var size: u32 = @sizeOf(u32);
+ const rc = system.getsockopt(op.socket, os.SOL.SOCKET, os.SO.ERROR, @ptrCast([*]u8, &err_code), &size);
+ assert(size == 4);
+ break :brk switch (darwin.getErrno(rc)) {
+ .SUCCESS => switch (@intToEnum(os.E, err_code)) {
+ .SUCCESS => void{},
+ .ACCES => error.PermissionDenied,
+ .PERM => error.PermissionDenied,
+ .ADDRINUSE => error.AddressInUse,
+ .ADDRNOTAVAIL => error.AddressNotAvailable,
+ .AFNOSUPPORT => error.AddressFamilyNotSupported,
+ .AGAIN => error.SystemResources,
+ .ALREADY => error.ConnectionPending,
+ .CONNREFUSED => error.ConnectionRefused,
+ // .FAULT => unreachable, // The socket structure address is outside the user's address space.
+ // .ISCONN => unreachable, // The socket is already connected.
+ .NETUNREACH => error.NetworkUnreachable,
+ // .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
+ // .PROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
+ .TIMEDOUT => error.ConnectionTimedOut,
+ .CONNRESET => error.ConnectionResetByPeer,
+ else => |err| asError(err),
+ },
+ else => |err| asError(err),
+ };
+ },
+ else => switch (darwin.getErrno(darwin.@"connect$NOCANCEL"(op.socket, &op.address.any, op.address.getOsSockLen()))) {
+ .SUCCESS => void{},
+ .ACCES => error.PermissionDenied,
+ .PERM => error.PermissionDenied,
+ .ADDRINUSE => error.AddressInUse,
+ .ADDRNOTAVAIL => error.AddressNotAvailable,
+ .AFNOSUPPORT => error.AddressFamilyNotSupported,
+ .AGAIN, .INPROGRESS => error.WouldBlock,
+ .ALREADY => error.ConnectionPending,
+ .CONNREFUSED => error.ConnectionRefused,
+ .CONNRESET => error.ConnectionResetByPeer,
+ .NETUNREACH => error.NetworkUnreachable,
+ .TIMEDOUT => error.ConnectionTimedOut,
+ else => |err| asError(err),
+ },
};
op.initiated = true;
@@ -562,7 +985,7 @@ pub const ReadError = error{
IsDir,
SystemResources,
Unseekable,
-} || os.UnexpectedError;
+} || Errno;
pub fn read(
self: *IO,
@@ -604,7 +1027,6 @@ pub fn read(
os.EAGAIN => error.WouldBlock,
os.EBADF => error.NotOpenForReading,
os.ECONNRESET => error.ConnectionResetByPeer,
- os.EFAULT => unreachable,
os.EINVAL => error.Alignment,
os.EIO => error.InputOutput,
os.EISDIR => error.IsDir,
@@ -613,7 +1035,7 @@ pub fn read(
os.ENXIO => error.Unseekable,
os.EOVERFLOW => error.Unseekable,
os.ESPIPE => error.Unseekable,
- else => error.Unexpected,
+ else => |err| asError(err),
};
}
}
@@ -621,7 +1043,12 @@ pub fn read(
);
}
-pub const RecvError = os.RecvFromError;
+pub const RecvError = error{
+ SystemResources,
+ ConnectionRefused,
+ ConnectionResetByPeer,
+ WouldBlock,
+} || Errno;
pub fn recv(
self: *IO,
@@ -648,13 +1075,37 @@ pub fn recv(
},
struct {
fn doOperation(op: anytype) RecvError!usize {
- return os.recv(op.socket, op.buf[0..op.len], 0);
+ const rc = system.@"recvfrom$NOCANCEL"(op.socket, op.buf, op.len, 0, null, null);
+ return switch (system.getErrno(rc)) {
+ .SUCCESS => @intCast(usize, rc),
+ .AGAIN => error.WouldBlock,
+ .NOMEM => error.SystemResources,
+ .CONNREFUSED => error.ConnectionRefused,
+ .CONNRESET => error.ConnectionResetByPeer,
+ else => |err| asError(err),
+ };
}
},
);
}
-pub const SendError = os.SendToError;
+pub const SendError = error{
+ AccessDenied,
+ AddressFamilyNotSupported,
+ BrokenPipe,
+ ConnectionResetByPeer,
+ FastOpenAlreadyInProgress,
+ FileNotFound,
+ MessageTooBig,
+ NameTooLong,
+ NetworkSubsystemFailed,
+ NetworkUnreachable,
+ NotDir,
+ SocketNotConnected,
+ SymLinkLoop,
+ SystemResources,
+ WouldBlock,
+} || Errno;
pub fn send(
self: *IO,
@@ -683,13 +1134,34 @@ pub fn send(
},
struct {
fn doOperation(op: anytype) SendError!usize {
- return os.sendto(op.socket, op.buf[0..op.len], op.flags, null, 0);
+ const rc = system.@"sendto$NOCANCEL"(op.socket, op.buf, op.len, op.flags, null, 0);
+ return switch (system.getErrno(rc)) {
+ .SUCCESS => @intCast(usize, rc),
+ .ACCES => error.AccessDenied,
+ .AGAIN => error.WouldBlock,
+ .ALREADY => error.FastOpenAlreadyInProgress,
+ .CONNRESET => error.ConnectionResetByPeer,
+ .MSGSIZE => error.MessageTooBig,
+ .NOBUFS => error.SystemResources,
+ .NOMEM => error.SystemResources,
+ .PIPE => error.BrokenPipe,
+ .AFNOSUPPORT => error.AddressFamilyNotSupported,
+ .LOOP => error.SymLinkLoop,
+ .NAMETOOLONG => error.NameTooLong,
+ .NOENT => error.FileNotFound,
+ .NOTDIR => error.NotDir,
+ .HOSTUNREACH => error.NetworkUnreachable,
+ .NETUNREACH => error.NetworkUnreachable,
+ .NOTCONN => error.SocketNotConnected,
+ .NETDOWN => error.NetworkSubsystemFailed,
+ else => |err| asError(err),
+ };
}
},
);
}
-pub const TimeoutError = error{Canceled} || os.UnexpectedError;
+pub const TimeoutError = error{Canceled} || Errno;
pub fn timeout(
self: *IO,
@@ -755,11 +1227,13 @@ pub fn write(
}
pub fn openSocket(family: u32, sock_type: u32, protocol: u32) !os.socket_t {
- const fd = try os.socket(family, sock_type | os.SOCK.NONBLOCK, protocol);
- errdefer os.close(fd);
+ const fd = try Syscall.socket(family, sock_type | os.SOCK.NONBLOCK, protocol);
+ errdefer {
+ Syscall.close(fd) catch {};
+ }
// darwin doesn't support os.MSG.NOSIGNAL, but instead a socket option to avoid SIGPIPE.
- try os.setsockopt(fd, os.SOL.SOCKET, os.SO.NOSIGPIPE, &mem.toBytes(@as(c_int, 1)));
+ try Syscall.setsockopt(fd, os.SOL.SOCKET, os.SO.NOSIGPIPE, &mem.toBytes(@as(c_int, 1)));
return fd;
}
@@ -775,7 +1249,7 @@ fn buffer_limit(buffer_len: usize) usize {
.macos, .ios, .watchos, .tvos => std.math.maxInt(i32),
else => std.math.maxInt(isize),
};
- return std.math.min(limit, buffer_len);
+ return @minimum(limit, buffer_len);
}
pub var global: IO = undefined;
diff --git a/src/io/io_linux.zig b/src/io/io_linux.zig
index 7abb01cc3..ea6c29284 100644
--- a/src/io/io_linux.zig
+++ b/src/io/io_linux.zig
@@ -2,49 +2,426 @@ const std = @import("std");
const assert = std.debug.assert;
const os = struct {
pub usingnamespace std.os;
- pub const ETIME = 62;
+ pub const EPERM = 1;
+ pub const ENOENT = 2;
+ pub const ESRCH = 3;
pub const EINTR = 4;
- pub const EAGAIN = 11;
+ pub const EIO = 5;
+ pub const ENXIO = 6;
+ pub const E2BIG = 7;
+ pub const ENOEXEC = 8;
pub const EBADF = 9;
- pub const ECONNABORTED = 103;
+ pub const ECHILD = 10;
+ pub const EAGAIN = 11;
+ pub const ENOMEM = 12;
+ pub const EACCES = 13;
pub const EFAULT = 14;
+ pub const ENOTBLK = 15;
+ pub const EBUSY = 16;
+ pub const EEXIST = 17;
+ pub const EXDEV = 18;
+ pub const ENODEV = 19;
+ pub const ENOTDIR = 20;
+ pub const EISDIR = 21;
pub const EINVAL = 22;
- pub const EMFILE = 24;
pub const ENFILE = 23;
- pub const ENOBUFS = 105;
- pub const ENOMEM = 12;
- pub const ENOTSOCK = 88;
- pub const EOPNOTSUPP = 95;
- pub const EPERM = 1;
- pub const EPROTO = 71;
- pub const EDQUOT = 69;
- pub const EIO = 5;
+ pub const EMFILE = 24;
+ pub const ENOTTY = 25;
+ pub const ETXTBSY = 26;
+ pub const EFBIG = 27;
pub const ENOSPC = 28;
- pub const EACCES = 13;
+ pub const ESPIPE = 29;
+ pub const EROFS = 30;
+ pub const EMLINK = 31;
+ pub const EPIPE = 32;
+ pub const EDOM = 33;
+ pub const ERANGE = 34;
+ pub const EDEADLK = 35;
+ pub const ENAMETOOLONG = 36;
+ pub const ENOLCK = 37;
+ pub const ENOSYS = 38;
+ pub const ENOTEMPTY = 39;
+ pub const ELOOP = 40;
+ pub const EWOULDBLOCK = 41;
+ pub const ENOMSG = 42;
+ pub const EIDRM = 43;
+ pub const ECHRNG = 44;
+ pub const EL2NSYNC = 45;
+ pub const EL3HLT = 46;
+ pub const EL3RST = 47;
+ pub const ELNRNG = 48;
+ pub const EUNATCH = 49;
+ pub const ENOCSI = 50;
+ pub const EL2HLT = 51;
+ pub const EBADE = 52;
+ pub const EBADR = 53;
+ pub const EXFULL = 54;
+ pub const ENOANO = 55;
+ pub const EBADRQC = 56;
+ pub const EBADSLT = 57;
+ pub const EDEADLOCK = 58;
+ pub const EBFONT = 59;
+ pub const ENOSTR = 60;
+ pub const ENODATA = 61;
+ pub const ETIME = 62;
+ pub const ENOSR = 63;
+ pub const ENONET = 64;
+ pub const ENOPKG = 65;
+ pub const EREMOTE = 66;
+ pub const ENOLINK = 67;
+ pub const EADV = 68;
+ pub const ESRMNT = 69;
+ pub const ECOMM = 70;
+ pub const EPROTO = 71;
+ pub const EMULTIHOP = 72;
+ pub const EDOTDOT = 73;
+ pub const EBADMSG = 74;
+ pub const EOVERFLOW = 75;
+ pub const ENOTUNIQ = 76;
+ pub const EBADFD = 77;
+ pub const EREMCHG = 78;
+ pub const ELIBACC = 79;
+ pub const ELIBBAD = 80;
+ pub const ELIBSCN = 81;
+ pub const ELIBMAX = 82;
+ pub const ELIBEXEC = 83;
+ pub const EILSEQ = 84;
+ pub const ERESTART = 85;
+ pub const ESTRPIPE = 86;
+ pub const EUSERS = 87;
+ pub const ENOTSOCK = 88;
+ pub const EDESTADDRREQ = 89;
+ pub const EMSGSIZE = 90;
+ pub const EPROTOTYPE = 91;
+ pub const ENOPROTOOPT = 92;
+ pub const EPROTONOSUPPORT = 93;
+ pub const ESOCKTNOSUPPORT = 94;
+ /// For Linux, EOPNOTSUPP is the real value
+ /// but it's ~the same and is incompatible across operating systems
+ /// https://lists.gnu.org/archive/html/bug-glibc/2002-08/msg00017.html
+ pub const ENOTSUP = 95;
+ pub const EPFNOSUPPORT = 96;
+ pub const EAFNOSUPPORT = 97;
pub const EADDRINUSE = 98;
pub const EADDRNOTAVAIL = 99;
- pub const EAFNOSUPPORT = 97;
- pub const EINPROGRESS = 115;
- pub const EALREADY = 114;
- pub const ECONNREFUSED = 111;
+ pub const ENETDOWN = 100;
+ pub const ENETUNREACH = 101;
+ pub const ENETRESET = 102;
+ pub const ECONNABORTED = 103;
pub const ECONNRESET = 104;
+ pub const ENOBUFS = 105;
pub const EISCONN = 106;
- pub const ENETUNREACH = 101;
- pub const ENOENT = 2;
- pub const EPROTOTYPE = 91;
- pub const ETIMEDOUT = 110;
- pub const EROFS = 30;
- pub const EISDIR = 21;
- pub const ENXIO = 6;
- pub const EOVERFLOW = 84;
- pub const ESPIPE = 29;
pub const ENOTCONN = 107;
- pub const EDESTADDRREQ = 89;
- pub const EMSGSIZE = 90;
- pub const EPIPE = 32;
+ pub const ESHUTDOWN = 108;
+ pub const ETOOMANYREFS = 109;
+ pub const ETIMEDOUT = 110;
+ pub const ECONNREFUSED = 111;
+ pub const EHOSTDOWN = 112;
+ pub const EHOSTUNREACH = 113;
+ pub const EALREADY = 114;
+ pub const EINPROGRESS = 115;
+ pub const ESTALE = 116;
+ pub const EUCLEAN = 117;
+ pub const ENOTNAM = 118;
+ pub const ENAVAIL = 119;
+ pub const EISNAM = 120;
+ pub const EREMOTEIO = 121;
+ pub const EDQUOT = 122;
+ pub const ENOMEDIUM = 123;
+ pub const EMEDIUMTYPE = 124;
pub const ECANCELED = 125;
- pub const EFBIG = 27;
+ pub const ENOKEY = 126;
+ pub const EKEYEXPIRED = 127;
+ pub const EKEYREVOKED = 128;
+ pub const EKEYREJECTED = 129;
+ pub const EOWNERDEAD = 130;
+ pub const ENOTRECOVERABLE = 131;
+ pub const ERFKILL = 132;
+ pub const EHWPOISON = 133;
+};
+
+pub const Errno = error{
+ EPERM,
+ ENOENT,
+ ESRCH,
+ EINTR,
+ EIO,
+ ENXIO,
+ E2BIG,
+ ENOEXEC,
+ EBADF,
+ ECHILD,
+ EAGAIN,
+ ENOMEM,
+ EACCES,
+ EFAULT,
+ ENOTBLK,
+ EBUSY,
+ EEXIST,
+ EXDEV,
+ ENODEV,
+ ENOTDIR,
+ EISDIR,
+ EINVAL,
+ ENFILE,
+ EMFILE,
+ ENOTTY,
+ ETXTBSY,
+ EFBIG,
+ ENOSPC,
+ ESPIPE,
+ EROFS,
+ EMLINK,
+ EPIPE,
+ EDOM,
+ ERANGE,
+ EDEADLK,
+ ENAMETOOLONG,
+ ENOLCK,
+ ENOSYS,
+ ENOTEMPTY,
+ ELOOP,
+ EWOULDBLOCK,
+ ENOMSG,
+ EIDRM,
+ ECHRNG,
+ EL2NSYNC,
+ EL3HLT,
+ EL3RST,
+ ELNRNG,
+ EUNATCH,
+ ENOCSI,
+ EL2HLT,
+ EBADE,
+ EBADR,
+ EXFULL,
+ ENOANO,
+ EBADRQC,
+ EBADSLT,
+ EDEADLOCK,
+ EBFONT,
+ ENOSTR,
+ ENODATA,
+ ETIME,
+ ENOSR,
+ ENONET,
+ ENOPKG,
+ EREMOTE,
+ ENOLINK,
+ EADV,
+ ESRMNT,
+ ECOMM,
+ EPROTO,
+ EMULTIHOP,
+ EDOTDOT,
+ EBADMSG,
+ EOVERFLOW,
+ ENOTUNIQ,
+ EBADFD,
+ EREMCHG,
+ ELIBACC,
+ ELIBBAD,
+ ELIBSCN,
+ ELIBMAX,
+ ELIBEXEC,
+ EILSEQ,
+ ERESTART,
+ ESTRPIPE,
+ EUSERS,
+ ENOTSOCK,
+ EDESTADDRREQ,
+ EMSGSIZE,
+ EPROTOTYPE,
+ ENOPROTOOPT,
+ EPROTONOSUPPORT,
+ ESOCKTNOSUPPORT,
+ ENOTSUP,
+ EPFNOSUPPORT,
+ EAFNOSUPPORT,
+ EADDRINUSE,
+ EADDRNOTAVAIL,
+ ENETDOWN,
+ ENETUNREACH,
+ ENETRESET,
+ ECONNABORTED,
+ ECONNRESET,
+ ENOBUFS,
+ EISCONN,
+ ENOTCONN,
+ ESHUTDOWN,
+ ETOOMANYREFS,
+ ETIMEDOUT,
+ ECONNREFUSED,
+ EHOSTDOWN,
+ EHOSTUNREACH,
+ EALREADY,
+ EINPROGRESS,
+ ESTALE,
+ EUCLEAN,
+ ENOTNAM,
+ ENAVAIL,
+ EISNAM,
+ EREMOTEIO,
+ EDQUOT,
+ ENOMEDIUM,
+ EMEDIUMTYPE,
+ ECANCELED,
+ ENOKEY,
+ EKEYEXPIRED,
+ EKEYREVOKED,
+ EKEYREJECTED,
+ EOWNERDEAD,
+ ENOTRECOVERABLE,
+ ERFKILL,
+ EHWPOISON,
+ Unexpected,
+};
+const errno_error_map: [135]Errno = brk: {
+ var errors: [135]Errno = undefined;
+ errors[0] = error.Unexpected;
+ errors[1] = error.EPERM;
+ errors[2] = error.ENOENT;
+ errors[3] = error.ESRCH;
+ errors[4] = error.EINTR;
+ errors[5] = error.EIO;
+ errors[6] = error.ENXIO;
+ errors[7] = error.E2BIG;
+ errors[8] = error.ENOEXEC;
+ errors[9] = error.EBADF;
+ errors[10] = error.ECHILD;
+ errors[11] = error.EAGAIN;
+ errors[12] = error.ENOMEM;
+ errors[13] = error.EACCES;
+ errors[14] = error.EFAULT;
+ errors[15] = error.ENOTBLK;
+ errors[16] = error.EBUSY;
+ errors[17] = error.EEXIST;
+ errors[18] = error.EXDEV;
+ errors[19] = error.ENODEV;
+ errors[20] = error.ENOTDIR;
+ errors[21] = error.EISDIR;
+ errors[22] = error.EINVAL;
+ errors[23] = error.ENFILE;
+ errors[24] = error.EMFILE;
+ errors[25] = error.ENOTTY;
+ errors[26] = error.ETXTBSY;
+ errors[27] = error.EFBIG;
+ errors[28] = error.ENOSPC;
+ errors[29] = error.ESPIPE;
+ errors[30] = error.EROFS;
+ errors[31] = error.EMLINK;
+ errors[32] = error.EPIPE;
+ errors[33] = error.EDOM;
+ errors[34] = error.ERANGE;
+ errors[35] = error.EDEADLK;
+ errors[36] = error.ENAMETOOLONG;
+ errors[37] = error.ENOLCK;
+ errors[38] = error.ENOSYS;
+ errors[39] = error.ENOTEMPTY;
+ errors[40] = error.ELOOP;
+ errors[41] = error.EWOULDBLOCK;
+ errors[42] = error.ENOMSG;
+ errors[43] = error.EIDRM;
+ errors[44] = error.ECHRNG;
+ errors[45] = error.EL2NSYNC;
+ errors[46] = error.EL3HLT;
+ errors[47] = error.EL3RST;
+ errors[48] = error.ELNRNG;
+ errors[49] = error.EUNATCH;
+ errors[50] = error.ENOCSI;
+ errors[51] = error.EL2HLT;
+ errors[52] = error.EBADE;
+ errors[53] = error.EBADR;
+ errors[54] = error.EXFULL;
+ errors[55] = error.ENOANO;
+ errors[56] = error.EBADRQC;
+ errors[57] = error.EBADSLT;
+ errors[58] = error.EDEADLOCK;
+ errors[59] = error.EBFONT;
+ errors[60] = error.ENOSTR;
+ errors[61] = error.ENODATA;
+ errors[62] = error.ETIME;
+ errors[63] = error.ENOSR;
+ errors[64] = error.ENONET;
+ errors[65] = error.ENOPKG;
+ errors[66] = error.EREMOTE;
+ errors[67] = error.ENOLINK;
+ errors[68] = error.EADV;
+ errors[69] = error.ESRMNT;
+ errors[70] = error.ECOMM;
+ errors[71] = error.EPROTO;
+ errors[72] = error.EMULTIHOP;
+ errors[73] = error.EDOTDOT;
+ errors[74] = error.EBADMSG;
+ errors[75] = error.EOVERFLOW;
+ errors[76] = error.ENOTUNIQ;
+ errors[77] = error.EBADFD;
+ errors[78] = error.EREMCHG;
+ errors[79] = error.ELIBACC;
+ errors[80] = error.ELIBBAD;
+ errors[81] = error.ELIBSCN;
+ errors[82] = error.ELIBMAX;
+ errors[83] = error.ELIBEXEC;
+ errors[84] = error.EILSEQ;
+ errors[85] = error.ERESTART;
+ errors[86] = error.ESTRPIPE;
+ errors[87] = error.EUSERS;
+ errors[88] = error.ENOTSOCK;
+ errors[89] = error.EDESTADDRREQ;
+ errors[90] = error.EMSGSIZE;
+ errors[91] = error.EPROTOTYPE;
+ errors[92] = error.ENOPROTOOPT;
+ errors[93] = error.EPROTONOSUPPORT;
+ errors[94] = error.ESOCKTNOSUPPORT;
+ errors[95] = error.ENOTSUP;
+ errors[96] = error.EPFNOSUPPORT;
+ errors[97] = error.EAFNOSUPPORT;
+ errors[98] = error.EADDRINUSE;
+ errors[99] = error.EADDRNOTAVAIL;
+ errors[100] = error.ENETDOWN;
+ errors[101] = error.ENETUNREACH;
+ errors[102] = error.ENETRESET;
+ errors[103] = error.ECONNABORTED;
+ errors[104] = error.ECONNRESET;
+ errors[105] = error.ENOBUFS;
+ errors[106] = error.EISCONN;
+ errors[107] = error.ENOTCONN;
+ errors[108] = error.ESHUTDOWN;
+ errors[109] = error.ETOOMANYREFS;
+ errors[110] = error.ETIMEDOUT;
+ errors[111] = error.ECONNREFUSED;
+ errors[112] = error.EHOSTDOWN;
+ errors[113] = error.EHOSTUNREACH;
+ errors[114] = error.EALREADY;
+ errors[115] = error.EINPROGRESS;
+ errors[116] = error.ESTALE;
+ errors[117] = error.EUCLEAN;
+ errors[118] = error.ENOTNAM;
+ errors[119] = error.ENAVAIL;
+ errors[120] = error.EISNAM;
+ errors[121] = error.EREMOTEIO;
+ errors[122] = error.EDQUOT;
+ errors[123] = error.ENOMEDIUM;
+ errors[124] = error.EMEDIUMTYPE;
+ errors[125] = error.ECANCELED;
+ errors[126] = error.ENOKEY;
+ errors[127] = error.EKEYEXPIRED;
+ errors[128] = error.EKEYREVOKED;
+ errors[129] = error.EKEYREJECTED;
+ errors[130] = error.EOWNERDEAD;
+ errors[131] = error.ENOTRECOVERABLE;
+ errors[132] = error.ERFKILL;
+ errors[133] = error.EHWPOISON;
+ errors[134] = error.Unexpected;
+ break :brk errors;
};
+pub fn asError(err: anytype) Errno {
+ return switch (err) {
+ 1...errno_error_map.len => errno_error_map[@intCast(u8, err)],
+ else => error.Unexpected,
+ };
+}
+
const timespec = std.os.system.timespec;
const linux = os.linux;
const IO_Uring = linux.IO_Uring;
@@ -315,7 +692,7 @@ pub const Completion = struct {
os.EOPNOTSUPP => error.OperationNotSupported,
os.EPERM => error.PermissionDenied,
os.EPROTO => error.ProtocolFailure,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else @intCast(os.socket_t, completion.result);
completion.callback(completion.context, completion, &result);
},
@@ -326,7 +703,7 @@ pub const Completion = struct {
os.EDQUOT => error.DiskQuota,
os.EIO => error.InputOutput,
os.ENOSPC => error.NoSpaceLeft,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else assert(completion.result == 0);
completion.callback(completion.context, completion, &result);
},
@@ -353,7 +730,7 @@ pub const Completion = struct {
os.EPERM => error.PermissionDenied,
os.EPROTOTYPE => error.ProtocolNotSupported,
os.ETIMEDOUT => error.ConnectionTimedOut,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else assert(completion.result == 0);
completion.callback(completion.context, completion, &result);
},
@@ -369,7 +746,7 @@ pub const Completion = struct {
os.EIO => error.InputOutput,
os.ENOSPC => error.NoSpaceLeft,
os.EROFS => error.ReadOnlyFileSystem,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else assert(completion.result == 0);
completion.callback(completion.context, completion, &result);
},
@@ -391,7 +768,7 @@ pub const Completion = struct {
os.ENXIO => error.Unseekable,
os.EOVERFLOW => error.Unseekable,
os.ESPIPE => error.Unseekable,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else @intCast(usize, completion.result);
completion.callback(completion.context, completion, &result);
},
@@ -410,7 +787,7 @@ pub const Completion = struct {
os.ENOTCONN => error.SocketNotConnected,
os.ENOTSOCK => error.FileDescriptorNotASocket,
os.ECONNRESET => error.ConnectionResetByPeer,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else @intCast(usize, completion.result);
completion.callback(completion.context, completion, &result);
},
@@ -437,7 +814,7 @@ pub const Completion = struct {
os.ENOTSOCK => error.FileDescriptorNotASocket,
os.EOPNOTSUPP => error.OperationNotSupported,
os.EPIPE => error.BrokenPipe,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else @intCast(usize, completion.result);
completion.callback(completion.context, completion, &result);
},
@@ -449,7 +826,7 @@ pub const Completion = struct {
},
os.ECANCELED => error.Canceled,
os.ETIME => {}, // A success.
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else unreachable;
completion.callback(completion.context, completion, &result);
},
@@ -473,7 +850,7 @@ pub const Completion = struct {
os.EPERM => error.AccessDenied,
os.EPIPE => error.BrokenPipe,
os.ESPIPE => error.Unseekable,
- else => error.Unexpected,
+ else => |errno| asError(errno),
} else @intCast(usize, completion.result);
completion.callback(completion.context, completion, &result);
},
@@ -533,7 +910,7 @@ pub const AcceptError = error{
OperationNotSupported,
PermissionDenied,
ProtocolFailure,
-} || os.UnexpectedError;
+} || Errno;
pub fn accept(
self: *IO,
@@ -575,7 +952,7 @@ pub const CloseError = error{
DiskQuota,
InputOutput,
NoSpaceLeft,
-} || os.UnexpectedError;
+} || Errno;
pub fn close(
self: *IO,
@@ -624,7 +1001,7 @@ pub const ConnectError = error{
PermissionDenied,
ProtocolNotSupported,
ConnectionTimedOut,
-} || os.UnexpectedError;
+} || Errno;
pub fn connect(
self: *IO,
@@ -668,7 +1045,7 @@ pub const FsyncError = error{
InputOutput,
NoSpaceLeft,
ReadOnlyFileSystem,
-} || os.UnexpectedError;
+} || Errno;
pub fn fsync(
self: *IO,
@@ -712,7 +1089,7 @@ pub const ReadError = error{
IsDir,
SystemResources,
Unseekable,
-} || os.UnexpectedError;
+} || Errno;
pub fn read(
self: *IO,
@@ -758,7 +1135,7 @@ pub const RecvError = error{
SystemResources,
SocketNotConnected,
FileDescriptorNotASocket,
-} || os.UnexpectedError;
+} || Errno;
pub fn recv(
self: *IO,
@@ -808,7 +1185,7 @@ pub const SendError = error{
FileDescriptorNotASocket,
OperationNotSupported,
BrokenPipe,
-} || os.UnexpectedError;
+} || Errno;
pub fn send(
self: *IO,
@@ -846,7 +1223,7 @@ pub fn send(
self.enqueue(completion);
}
-pub const TimeoutError = error{Canceled} || os.UnexpectedError;
+pub const TimeoutError = error{Canceled} || Errno;
pub fn timeout(
self: *IO,
@@ -893,7 +1270,7 @@ pub const WriteError = error{
Unseekable,
AccessDenied,
BrokenPipe,
-} || os.UnexpectedError;
+} || Errno;
pub fn write(
self: *IO,