Conversation
Collaborator
|
Reviewed and tested Verified
On the designThe three-part predicate in
Coverage across I also checked whether |
macOS has no AF_UNIX SOCK_SEQPACKET, so sys_socketpair substitutes
SOCK_DGRAM. A macOS AF_UNIX datagram socket reports ECONNRESET (errno
54 -> Linux 104) on recv/read once the peer closes, whereas Linux
SEQPACKET returns a clean EOF (0). Rust std uses AF_UNIX SOCK_SEQPACKET
socketpair as its exec CLOEXEC status channel and treats a recv error
there as unreachable, so every Rust program that spawns a subprocess
aborted with SIGABRT ("the CLOEXEC pipe failed: ... ConnectionReset").
On Ubuntu 25.10, whose coreutils are the Rust uutils build, this reached
ordinary shell usage.
recv_eof_or_errno() folds that peer-close ECONNRESET into a clean EOF.
It fires only when errno is ECONNRESET, the guest's cached SO_TYPE is
SEQPACKET, and the pinned host fd is an AF_UNIX datagram socket -- the
two facts that together identify the socketpair substitute. This leaves
alone: genuine AF_UNIX SOCK_DGRAM sockets (Linux never returns EOF
there, it blocks or reports EAGAIN); the AF_UNIX SOCK_STREAM substitute
used for socket()/accept SEQPACKET (a genuine abort there is a real
reset); and INET UDP (ICMP-unreachable ECONNRESET, which Linux surfaces
as ECONNREFUSED). Probing the pinned host fd on the rare error tail is
race-free against guest fd reuse and off the socket hot path.
Close #260
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
macOS has no AF_UNIX SOCK_SEQPACKET, so sys_socketpair substitutes SOCK_DGRAM. A macOS AF_UNIX datagram socket reports ECONNRESET (errno 54 -> Linux 104) on recv/read once the peer closes, whereas Linux never surfaces ECONNRESET on an AF_UNIX datagram receive -- SEQPACKET returns a clean EOF (0). Rust std uses an AF_UNIX SOCK_SEQPACKET socketpair as its exec CLOEXEC status channel and treats a recv error there as unreachable, so every Rust program that spawns a subprocess aborted with SIGABRT ("the CLOEXEC pipe failed: ... ConnectionReset"). On Ubuntu 25.10, whose coreutils are the Rust uutils build, this reached ordinary shell usage.
recv_eof_or_errno() folds the substitute's peer-close ECONNRESET into a clean EOF. It scopes the translation by probing the pinned host fd (getsockopt SO_TYPE + getsockname) and firing only for AF_UNIX SOCK_DGRAM, so a genuine reset on the AF_UNIX SOCK_STREAM substitute (socket()/accept SEQPACKET) or an INET UDP ICMP-unreachable ECONNRESET is left untouched. Probing the pinned host fd on the rare error tail is race-free against guest fd reuse and off the socket hot path. It is applied at every receive site: sys_recvfrom, both sys_recvmsg paths, sys_recvmmsg, sys_read, sys_readv, and the vCPU-loop fast-path read. The recvfrom/recvmsg/recvmmsg EOF paths also write back the empty addrlen/msg_namelen/msg_controllen/msg_flags a real 0-length receive would report.
Close #260
Summary by cubic
Treat AF_UNIX SEQPACKET-over-DGRAM peer close as EOF on macOS to match Linux, fixing Rust subprocess aborts caused by ECONNRESET. Applies to all recv/read paths, clears address/control metadata, and stops recvmmsg(vlen>1) at EOF to avoid hangs.
recv_eof_or_errno()to fold host ECONNRESET into EOF only for AF_UNIXSOCK_DGRAMwhen the guest cached type isSOCK_SEQPACKET(viaSO_TYPE+getsockname), preserving errno across probes.sys_recvfrom, bothsys_recvmsgpaths,sys_recvmmsg(records one empty message, then ends the batch),sys_read,sys_readv, and the vCPU fast-path read.SOCK_STREAM, genuine AF_UNIXSOCK_DGRAM, and INET UDP (ICMP unreachable).addrlen/msg_namelen/msg_controllen/msg_flagsto match Linux.recv/read/readv/recvfrom/recvmsg/recvmmsg, no fold for AF_UNIXSOCK_DGRAM, andrecvmmsg(vlen>1)does not hang.Written for commit 1e42743. Summary will update on new commits.