Merge branch 'accept-close-race-5279' of https://github.com/endragor/Nim into endragor-accept-close-race-5279
This commit is contained in:
commit
4790b6b203
5 changed files with 114 additions and 44 deletions
|
|
@ -753,26 +753,6 @@ when defined(windows) or defined(nimdoc):
|
|||
let dwLocalAddressLength = Dword(sizeof(Sockaddr_in) + 16)
|
||||
let dwRemoteAddressLength = Dword(sizeof(Sockaddr_in) + 16)
|
||||
|
||||
template completeAccept() {.dirty.} =
|
||||
var listenSock = socket
|
||||
let setoptRet = setsockopt(clientSock, SOL_SOCKET,
|
||||
SO_UPDATE_ACCEPT_CONTEXT, addr listenSock,
|
||||
sizeof(listenSock).SockLen)
|
||||
if setoptRet != 0: raiseOSError(osLastError())
|
||||
|
||||
var localSockaddr, remoteSockaddr: ptr SockAddr
|
||||
var localLen, remoteLen: int32
|
||||
getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength,
|
||||
dwLocalAddressLength, dwRemoteAddressLength,
|
||||
addr localSockaddr, addr localLen,
|
||||
addr remoteSockaddr, addr remoteLen)
|
||||
register(clientSock.AsyncFD)
|
||||
# TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186
|
||||
retFuture.complete(
|
||||
(address: $inet_ntoa(cast[ptr Sockaddr_in](remoteSockAddr).sin_addr),
|
||||
client: clientSock.AsyncFD)
|
||||
)
|
||||
|
||||
template failAccept(errcode) =
|
||||
if flags.isDisconnectionError(errcode):
|
||||
var newAcceptFut = acceptAddr(socket, flags)
|
||||
|
|
@ -785,6 +765,29 @@ when defined(windows) or defined(nimdoc):
|
|||
else:
|
||||
retFuture.fail(newException(OSError, osErrorMsg(errcode)))
|
||||
|
||||
template completeAccept() {.dirty.} =
|
||||
var listenSock = socket
|
||||
let setoptRet = setsockopt(clientSock, SOL_SOCKET,
|
||||
SO_UPDATE_ACCEPT_CONTEXT, addr listenSock,
|
||||
sizeof(listenSock).SockLen)
|
||||
if setoptRet != 0:
|
||||
let errcode = osLastError()
|
||||
checkCloseError clientSock.closeSocket()
|
||||
failAccept(errcode)
|
||||
else:
|
||||
var localSockaddr, remoteSockaddr: ptr SockAddr
|
||||
var localLen, remoteLen: int32
|
||||
getAcceptExSockaddrs(addr lpOutputBuf[0], dwReceiveDataLength,
|
||||
dwLocalAddressLength, dwRemoteAddressLength,
|
||||
addr localSockaddr, addr localLen,
|
||||
addr remoteSockaddr, addr remoteLen)
|
||||
register(clientSock.AsyncFD)
|
||||
# TODO: IPv6. Check ``sa_family``. http://stackoverflow.com/a/9212542/492186
|
||||
retFuture.complete(
|
||||
(address: $inet_ntoa(cast[ptr Sockaddr_in](remoteSockAddr).sin_addr),
|
||||
client: clientSock.AsyncFD)
|
||||
)
|
||||
|
||||
var ol = PCustomOverlapped()
|
||||
GC_ref(ol)
|
||||
ol.data = CompletionData(fd: socket, cb:
|
||||
|
|
|
|||
|
|
@ -22,11 +22,12 @@ const useWinVersion = defined(Windows) or defined(nimdoc)
|
|||
when useWinVersion:
|
||||
import winlean
|
||||
export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
|
||||
WSANOTINITIALISED, WSAENOTSOCK, WSAEINPROGRESS, WSAEINTR,
|
||||
WSAEDISCON, ERROR_NETNAME_DELETED
|
||||
else:
|
||||
import posix
|
||||
export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
|
||||
EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET
|
||||
EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET, EBADF
|
||||
export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length
|
||||
|
||||
export SocketHandle, Sockaddr_in, Addrinfo, INADDR_ANY, SockAddr, SockLen,
|
||||
|
|
@ -619,3 +620,28 @@ proc selectWrite*(writefds: var seq[SocketHandle],
|
|||
when defined(Windows):
|
||||
var wsa: WSAData
|
||||
if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())
|
||||
|
||||
proc checkCloseError*(ret: cint) =
|
||||
## Asserts that the return value of close() or closeSocket() syscall
|
||||
## does not indicate a programming error (such as invalid descriptor).
|
||||
## This must only be used when an error has already occurred and
|
||||
## you are performing a cleanup.
|
||||
## Otherwise, error handling must be performed as usual.
|
||||
##
|
||||
## This procedure must be called right after performing the syscall. Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## let ret = someSysCall()
|
||||
## if ret != 0:
|
||||
## let errcode = osLastError()
|
||||
## checkCloseError sock.closeSocket()
|
||||
## raise newException(OSError, osErrorMsg(errcode))
|
||||
|
||||
if ret != 0:
|
||||
let errcode = osLastError()
|
||||
when useWinVersion:
|
||||
doAssert(errcode.int32 notin {WSANOTINITIALISED, WSAENOTSOCK,
|
||||
WSAEINPROGRESS, WSAEINTR, WSAEWOULDBLOCK})
|
||||
else:
|
||||
doAssert(errcode.int32 notin {EBADF})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue