Repository navigation
Port the give-up API of 3.2.10.0 to 3.2.12.0 to master - #631
Open
kazu-yamamoto wants to merge 15 commits into
Open
kazu-yamamoto wants to merge 15 commits into
kazu-yamamoto wants to merge 15 commits into
Conversation
A thread blocked on a socket was stopped either by closing the socket under it or by an asynchronous exception, and both are going away: GHC is removing the evtClose delivery closeFdWith relies on, and an asynchronous exception does not reach a thread blocked in a socket call on Windows at all. withReadable takes an STM action beside the operation; whichever settles first decides, and an operation which has completed wins a tie. acceptWith, recvBufWith, recvBufFromWith and the ByteString recvWith and recvFromWith are built from it. Nothing is closed and no thread is interrupted to make the caller return. On Windows there is no readiness to wait for, so the operation runs in a thread of its own and is ended with CancelIoEx, which leaves the socket usable; that is Network.Socket.Win32.Cancel. The four readiness functions cannot work there and say so rather than blocking for ever. isClosedSocketError and isTransientAcceptError name what an accept loop has to tell apart: a socket closed under it, one queued connection which failed, and the rest. They read ioe_errno, which on Windows now keeps the Winsock code rather than dropping it -- Winsock reports every error as OtherError, so the code was the only thing telling them apart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gracefulClose had a code path per platform and a watchdog thread to end the receive. recvBufWith replaces all of it: one recvEOF, no GHC.Event, no System.Timeout, no thread to kill and no CPP. It keeps the bounded drain the watchdog scheme grew, because data left unread makes close send RST rather than FIN, and it therefore keeps to its timeout on Windows, where System.Timeout cannot cut a receive short at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A datagram sent to a port nobody has bound comes back as an ICMP unreachable, and Winsock reports it to the next recvfrom even on a socket which was never connected: one reply bouncing off a client which had gone ended a server's receive loop. socket turns that off for a datagram socket with WSAIoctl(SIO_UDP_CONNRESET, FALSE) and connect turns it back on, which is where POSIX puts it. A socket adopted with mkSocket keeps Winsock's default, since nothing there knows it is a datagram socket. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A bare close(2) where the caller knows no thread is waiting on the socket. 'close' goes through the IO manager to tell a waiter, which locks every capability and finds nobody. Doing it outside the library is not possible: the socket has to be invalidated so that its finalizer does not close the descriptor a second time, and invalidateSocket is not exported. (cherry picked from commit 4a2fcae) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
atomically and orElse have been unused since 3.2.10.0; -Wunused-imports says so on a clean build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit eef109b)
unsafeGracefulClose is gracefulClose ending with unsafeClose, for a caller which knows no other thread waits on the socket. recvMsgWith is recvMsg which the caller can give up on, so that a server reading control messages can be stopped by being told. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit ebffe63)
WSASendMsg returns 0 on success and puts the length in its out parameter, which was not read, so sendMsg always returned 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
withWritable is withReadable for writing. On it are built sendBufWith, sendBufToWith, connectWith, and in Network.Socket.ByteString sendWith, sendAllWith, sendToWith, sendManyWith and sendMsgWith. On Windows a send given up on is cancelled with CancelIoEx, may have sent part of its data, and leaves the socket unable to send, so a stream given up on is to be closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recvWith reads once without waiting, and an error there, such as the ICMP unreachable of a connected datagram socket, was taken as nothing to read. The error is gone once read, so the wait which followed gave up instead of raising it. On Windows recvBufNoWait also answered -1 for a recv which failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The WINIO receives took WSAECONNRESET for the end of a stream and returned 0. On a datagram socket it reports an ICMP unreachable, which MIO raises and POSIX raises as ECONNREFUSED, so it is raised there too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recvBufMsgWith and sendBufMsgWith, the give-up functions missing from Network.Socket.Address (connectWith, sendToWith, sendBufToWith, recvBufFromWith and the two above), and sendWith, sendAllWith and recvWith for lazy ByteStrings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sendAllWith took 19.5 us per small send on macOS against sendAll's 2.7 us; with poll(2) first it takes 3.3 us. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A give-up cancelled with CancelIoEx(fd, NULL), which also ended other threads' operations on the socket. The give-ups of particular operations now issue them with an OVERLAPPED of their own (cbits/ overlapped.c) and cancel that one alone. withReadable and withWritable cannot, and say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit e4a671b)
POSIX raises an ICMP port unreachable as ECONNREFUSED (NoSuchThing) and Winsock as WSAECONNRESET (OtherError), so the error type cannot tell it apart portably. This reads the code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
This brings the changes released in 3.2.10.0, 3.2.11.0 and 3.2.12.0 from the v3.2 branch to master (3.3.0.0).
acceptWith,connectWith, therecv/sendfamilies'Withversions,withReadableandwithWritable.CancelIoExwith its ownOVERLAPPED).unsafeClose,unsafeGracefulClose,isClosedSocketError,isTransientAcceptErrorandisPortUnreachableError.gracefulClosewaits for the peer's FIN throughrecvBufWithon every platform.WSAECONNRESETinstead of being taken as an empty datagram.The commits are those of v3.2, rebased onto master after #630. CHANGELOG lists them under 3.3.0.0.
🤖 Generated with Claude Code