fixes #19973; switch to poll on posix (#20212)

* fixes #19973; switch to poll on posix

* it is fd

* exclude lwip

* fixes lwip

* rename select to timeoutRead

* refactor into timeoutRead/timeoutWrite

* refactor common parts

Co-authored-by: xflywind <43030857+xflywind@users.noreply.github.com>
This commit is contained in:
ringabout 2022-08-24 00:58:08 +08:00 • committed by GitHub
commit 2b8f0a7971
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -203,6 +203,30 @@ type
when defined(nimHasStyleChecks): when defined(nimHasStyleChecks):
{.pop.} {.pop.}
when defined(posix) and not defined(lwip):
from posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds
template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int =
var tpollfd: TPollfd
tpollfd.fd = cast[cint](x)
tpollfd.events = y
posix.poll(addr(tpollfd), Tnfds(1), timeout)
proc timeoutRead(fd: var SocketHandle, timeout = 500): int =
when defined(windows) or defined(lwip):
var fds = @[fd]
selectRead(fds, timeout)
else:
monitorPollEvent(fd, POLLIN or POLLPRI, timeout)
proc timeoutWrite(fd: var SocketHandle, timeout = 500): int =
when defined(windows) or defined(lwip):
var fds = @[fd]
selectWrite(fds, timeout)
else:
monitorPollEvent(fd, POLLOUT or POLLWRBAND, timeout)
proc socketError*(socket: Socket, err: int = -1, async = false, proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode, lastError = (-1).OSErrorCode,
flags: set[SocketFlag] = {}) {.gcsafe.} flags: set[SocketFlag] = {}) {.gcsafe.}
@ -1308,14 +1332,6 @@ proc hasDataBuffered*(s: Socket): bool =
if s.isSsl and not result: if s.isSsl and not result:
result = s.sslHasPeekChar result = s.sslHasPeekChar
proc select(readfd: Socket, timeout = 500): int =
## Used for socket operation timeouts.
if readfd.hasDataBuffered:
return 1
var fds = @[readfd.fd]
result = selectRead(fds, timeout)
proc isClosed(socket: Socket): bool = proc isClosed(socket: Socket): bool =
socket.fd == osInvalidSocket socket.fd == osInvalidSocket
@ -1429,7 +1445,9 @@ proc waitFor(socket: Socket, waited: var Duration, timeout, size: int,
return min(sslPending, size) return min(sslPending, size)
var startTime = getMonoTime() var startTime = getMonoTime()
let selRet = select(socket, (timeout - waited.inMilliseconds).int) let selRet = if socket.hasDataBuffered: 1
else:
timeoutRead(socket.fd, (timeout - waited.inMilliseconds).int)
if selRet < 0: raiseOSError(osLastError()) if selRet < 0: raiseOSError(osLastError())
if selRet != 1: if selRet != 1:
raise newException(TimeoutError, "Call to '" & funcName & "' timed out.") raise newException(TimeoutError, "Call to '" & funcName & "' timed out.")
@ -2063,8 +2081,7 @@ proc connect*(socket: Socket, address: string, port = Port(0),
socket.fd.setBlocking(false) socket.fd.setBlocking(false)
socket.connectAsync(address, port, socket.domain) socket.connectAsync(address, port, socket.domain)
var s = @[socket.fd] if timeoutWrite(socket.fd, timeout) != 1:
if selectWrite(s, timeout) != 1:
raise newException(TimeoutError, "Call to 'connect' timed out.") raise newException(TimeoutError, "Call to 'connect' timed out.")
else: else:
let res = getSockOptInt(socket.fd, SOL_SOCKET, SO_ERROR) let res = getSockOptInt(socket.fd, SOL_SOCKET, SO_ERROR)