authorgravatar for kenta@lithdew.netlithdew <kenta@lithdew.net> 2021-04-02 05:28:25+09:00
committergravatar for mail@isaacfreund.comIsaac Freund <mail@isaacfreund.com> 2021-04-06 11:30:20+02:00
log2bfc6d14d500dcaf66b8ee7d24637e25e3795a5e
tree590a0fd6101060b5b7e57ae160dfda3552bc2327
parent83a2665772578f6262afc858613023738a7d25ef

os/linux: return error on EALREADY for connect() and getsockoptError()

When a connected socket file descriptor on Linux is re-acquired after being closed, through fuzz testing, it appears that a subsequent attempt to establish a connection with the file descriptor causes EALREADY to be reported. Instead of panicking, choose to return error.ConnectionPending to allow for users to handle this fairly rare case.

1 files changed, 5 insertions(+), 2 deletions(-)

lib/std/os.zig+5-2
...@@ -3254,6 +3254,9 @@ pub const ConnectError = error{...@@ -3254,6 +3254,9 @@ pub const ConnectError = error{
32543254
3255 /// Connection was reset by peer before connect could complete.3255 /// Connection was reset by peer before connect could complete.
3256 ConnectionResetByPeer,3256 ConnectionResetByPeer,
3257
3258 /// Socket is non-blocking and already has a pending connection in progress.
3259 ConnectionPending,
3257} || UnexpectedError;3260} || UnexpectedError;
32583261
3259/// Initiate a connection on a socket.3262/// Initiate a connection on a socket.
...@@ -3294,7 +3297,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne...@@ -3294,7 +3297,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne
3294 EADDRNOTAVAIL => return error.AddressNotAvailable,3297 EADDRNOTAVAIL => return error.AddressNotAvailable,
3295 EAFNOSUPPORT => return error.AddressFamilyNotSupported,3298 EAFNOSUPPORT => return error.AddressFamilyNotSupported,
3296 EAGAIN, EINPROGRESS => return error.WouldBlock,3299 EAGAIN, EINPROGRESS => return error.WouldBlock,
3297 EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.3300 EALREADY => return error.ConnectionPending,
3298 EBADF => unreachable, // sockfd is not a valid open file descriptor.3301 EBADF => unreachable, // sockfd is not a valid open file descriptor.
3299 ECONNREFUSED => return error.ConnectionRefused,3302 ECONNREFUSED => return error.ConnectionRefused,
3300 ECONNRESET => return error.ConnectionResetByPeer,3303 ECONNRESET => return error.ConnectionResetByPeer,
...@@ -3325,7 +3328,7 @@ pub fn getsockoptError(sockfd: fd_t) ConnectError!void {...@@ -3325,7 +3328,7 @@ pub fn getsockoptError(sockfd: fd_t) ConnectError!void {
3325 EADDRNOTAVAIL => return error.AddressNotAvailable,3328 EADDRNOTAVAIL => return error.AddressNotAvailable,
3326 EAFNOSUPPORT => return error.AddressFamilyNotSupported,3329 EAFNOSUPPORT => return error.AddressFamilyNotSupported,
3327 EAGAIN => return error.SystemResources,3330 EAGAIN => return error.SystemResources,
3328 EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed.3331 EALREADY => return error.ConnectionPending,
3329 EBADF => unreachable, // sockfd is not a valid open file descriptor.3332 EBADF => unreachable, // sockfd is not a valid open file descriptor.
3330 ECONNREFUSED => return error.ConnectionRefused,3333 ECONNREFUSED => return error.ConnectionRefused,
3331 EFAULT => unreachable, // The socket structure address is outside the user's address space.3334 EFAULT => unreachable, // The socket structure address is outside the user's address space.