os: expect ETIMEDOUT, ECONNRESET, ENOTCONN from recvfrom & read family

reads on eg. connected TCP sockets can fail with ETIMEDOUT, and ENOTCONN
happens eg. if you try to read a TCP socket that has not been connected
yet.

interestingly read() was already handling CONNRESET & TIMEDOUT, but
readv(), pread(), and preadv() were somewhat inconsistent.
This commit is contained in:
Lauri Tirkkonen 2023-07-27 22:31:51 +09:00 committed by Andrew Kelley
parent 280140595f
commit 19af8aac82
4 changed files with 24 additions and 0 deletions

View File

@ -686,6 +686,7 @@ pub const ReadError = error{
ConnectionResetByPeer,
ConnectionTimedOut,
NotOpenForReading,
SocketNotConnected,
// Windows only
NetNameDeleted,
@ -732,6 +733,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
.NOTCAPABLE => return error.AccessDenied,
@ -760,6 +762,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
else => |err| return unexpectedErrno(err),
@ -800,6 +803,9 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
.NOTCAPABLE => return error.AccessDenied,
else => |err| return unexpectedErrno(err),
}
@ -819,7 +825,9 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
else => |err| return unexpectedErrno(err),
}
}
@ -864,7 +872,9 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
.NXIO => return error.Unseekable,
.SPIPE => return error.Unseekable,
.OVERFLOW => return error.Unseekable,
@ -897,7 +907,9 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
.NXIO => return error.Unseekable,
.SPIPE => return error.Unseekable,
.OVERFLOW => return error.Unseekable,
@ -1009,6 +1021,9 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
.NXIO => return error.Unseekable,
.SPIPE => return error.Unseekable,
.OVERFLOW => return error.Unseekable,
@ -1035,6 +1050,9 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
.ISDIR => return error.IsDir,
.NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketNotConnected,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
.NXIO => return error.Unseekable,
.SPIPE => return error.Unseekable,
.OVERFLOW => return error.Unseekable,
@ -6624,6 +6642,7 @@ pub const RecvFromError = error{
SystemResources,
ConnectionResetByPeer,
ConnectionTimedOut,
/// The socket has not been bound.
SocketNotBound,
@ -6663,6 +6682,7 @@ pub fn recvfrom(
.WSAENETDOWN => return error.NetworkSubsystemFailed,
.WSAENOTCONN => return error.SocketNotConnected,
.WSAEWOULDBLOCK => return error.WouldBlock,
.WSAETIMEDOUT => return error.ConnectionTimedOut,
// TODO: handle more errors
else => |err| return windows.unexpectedWSAError(err),
}
@ -6682,6 +6702,7 @@ pub fn recvfrom(
.NOMEM => return error.SystemResources,
.CONNREFUSED => return error.ConnectionRefused,
.CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.ConnectionTimedOut,
else => |err| return unexpectedErrno(err),
}
}

View File

@ -917,6 +917,7 @@ fn preadMin(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usize {
error.Unseekable => return error.UnableToReadElfFile,
error.ConnectionResetByPeer => return error.UnableToReadElfFile,
error.ConnectionTimedOut => return error.UnableToReadElfFile,
error.SocketNotConnected => return error.UnableToReadElfFile,
error.NetNameDeleted => return error.UnableToReadElfFile,
error.Unexpected => return error.Unexpected,
error.InputOutput => return error.FileSystem,

View File

@ -531,6 +531,7 @@ pub const File = struct {
BrokenPipe,
ConnectionResetByPeer,
ConnectionTimedOut,
SocketNotConnected,
NotOpenForReading,
WouldBlock,
AccessDenied,

View File

@ -5682,6 +5682,7 @@ const FmtError = error{
NotOpenForWriting,
UnsupportedEncoding,
ConnectionResetByPeer,
SocketNotConnected,
LockViolation,
NetNameDeleted,
InvalidArgument,