From 67442471ae4504bc074c8bb02308613fadc199f8 Mon Sep 17 00:00:00 2001 From: bptato <60043228+bptato@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:15:39 +0200 Subject: [PATCH] Fix broken poll and nfds_t bindings (#24331) This fixes several cases of the Nim binding of nfds_t being inconsistent with the target platform signedness and/or size. Additionally, it fixes poll's third argument (timeout) being set to Nim "int" when it should have been "cint". The former is the same issue that #23045 had attempted to fix, but failed because it only considered Linux. (Also, it was only applied to version 2.0, so the two branches now have incompatible versions of the same bug.) Notes: * SVR4's original "unsigned long" definition is cloned by Linux and Haiku. Nim got this right for Haiku and Linux-amd64, but it was wrong on non-amd64 Linux. * Zephyr does not have nfds_t, but simply uses (signed) "int". This was already correctly reflected by Nim. * OpenBSD poll.h uses "unsigned int", and other BSD derivatives follow suit. This being the most commonly copied definition, the fallback case now returns cuint. (This also seems to be correct for the OS X headers I could find on the web.) * This changes Nintendo Switch nfds_t to cuint from culong. It is purportedly a FreeBSD derivative, so I *think* this is correct, but I can't tell because I don't have access to the Nintendo Switch headers. I have also moved the platform-specific Tnfds to posix.nim so that we can reuse the fallback logic on all platforms. (e.g. specifying the size in posix_linux_amd64 only to then use when defined(linux) in posix_other seems redundant.) --- lib/posix/posix.nim | 16 +++++++++++++++- lib/posix/posix_haiku.nim | 2 -- lib/posix/posix_linux_amd64.nim | 2 -- lib/posix/posix_macos_amd64.nim | 2 -- lib/posix/posix_nintendoswitch.nim | 2 -- lib/posix/posix_openbsd_amd64.nim | 2 -- lib/posix/posix_other.nim | 7 ------- lib/pure/ioselects/ioselectors_poll.nim | 2 +- lib/pure/net.nim | 6 +++--- 9 files changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index d85c84a486..ca3ca12757 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -1095,7 +1095,21 @@ proc setprotoent*(a1: cint) {.importc, header: "".} proc setservent*(a1: cint) {.importc, header: "".} when not defined(lwip): - proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {. + # Linux and Haiku emulate SVR4, which used unsigned long. + # Meanwhile, BSD derivatives had used unsigned int; we will use this + # for the else case, because it is more widely cloned than SVR4's + # behavior. + when defined(linux) or defined(haiku): + type + Tnfds* {.importc: "nfds_t", header: "".} = culong + elif defined(zephyr): + type + Tnfds* = distinct cint + else: + type + Tnfds* {.importc: "nfds_t", header: "".} = cuint + + proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {. importc, header: "", sideEffect.} proc realpath*(name, resolved: cstring): cstring {. diff --git a/lib/posix/posix_haiku.nim b/lib/posix/posix_haiku.nim index ba579778fa..6e325cb659 100644 --- a/lib/posix/posix_haiku.nim +++ b/lib/posix/posix_haiku.nim @@ -519,8 +519,6 @@ type events*: cshort ## The input event flags (see below). revents*: cshort ## The output event flags (see below). - Tnfds* {.importc: "nfds_t", header: "".} = culong - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_linux_amd64.nim b/lib/posix/posix_linux_amd64.nim index 8d11c507d7..7a9126abed 100644 --- a/lib/posix/posix_linux_amd64.nim +++ b/lib/posix/posix_linux_amd64.nim @@ -563,8 +563,6 @@ type events*: cshort ## The input event flags (see below). revents*: cshort ## The output event flags (see below). - Tnfds* {.importc: "nfds_t", header: "".} = culong - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_macos_amd64.nim b/lib/posix/posix_macos_amd64.nim index 59c4c65509..2b5dea69f4 100644 --- a/lib/posix/posix_macos_amd64.nim +++ b/lib/posix/posix_macos_amd64.nim @@ -533,8 +533,6 @@ type events*: cshort ## The input event flags (see below). revents*: cshort ## The output event flags (see below). - Tnfds* {.importc: "nfds_t", header: "".} = cint - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim index b66563695c..fdc4e590e4 100644 --- a/lib/posix/posix_nintendoswitch.nim +++ b/lib/posix/posix_nintendoswitch.nim @@ -484,8 +484,6 @@ type events*: cshort ## The input event flags (see below). revents*: cshort ## The output event flags (see below). - Tnfds* {.importc: "nfds_t", header: "".} = culong - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_openbsd_amd64.nim b/lib/posix/posix_openbsd_amd64.nim index 555980ed78..9244ce78cc 100644 --- a/lib/posix/posix_openbsd_amd64.nim +++ b/lib/posix/posix_openbsd_amd64.nim @@ -517,8 +517,6 @@ type events*: cshort ## The input event flags (see below). revents*: cshort ## The output event flags (see below). - Tnfds* {.importc: "nfds_t", header: "".} = cint - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim index 9804ab0ba6..6301216d4c 100644 --- a/lib/posix/posix_other.nim +++ b/lib/posix/posix_other.nim @@ -604,13 +604,6 @@ when not defined(lwip): events*: cshort ## The input event flags (see below). revents*: cshort ## The output event flags (see below). - when defined(zephyr): - type - Tnfds* = distinct cint - else: - type - Tnfds* {.importc: "nfds_t", header: "".} = cint - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/pure/ioselects/ioselectors_poll.nim b/lib/pure/ioselects/ioselectors_poll.nim index 7c53471563..6f50a5234d 100644 --- a/lib/pure/ioselects/ioselectors_poll.nim +++ b/lib/pure/ioselects/ioselectors_poll.nim @@ -231,7 +231,7 @@ proc selectInto*[T](s: Selector[T], timeout: int, verifySelectParams(timeout) s.withPollLock(): - let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), timeout) + let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), cint(timeout)) if count < 0: result = 0 let err = osLastError() diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 8ca1ab8259..6fecb8b8ef 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -211,7 +211,7 @@ when defined(nimHasStyleChecks): when defined(posix) and not defined(lwip): from std/posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds - template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int = + template monitorPollEvent(x: var SocketHandle, y, timeout: cint): int = var tpollfd: TPollfd tpollfd.fd = cast[cint](x) tpollfd.events = y @@ -222,14 +222,14 @@ proc timeoutRead(fd: var SocketHandle, timeout = 500): int = var fds = @[fd] selectRead(fds, timeout) else: - monitorPollEvent(fd, POLLIN or POLLPRI, timeout) + monitorPollEvent(fd, POLLIN or POLLPRI, cint(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) + monitorPollEvent(fd, POLLOUT or POLLWRBAND, cint(timeout)) proc socketError*(socket: Socket, err: int = -1, async = false, lastError = (-1).OSErrorCode,