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.)
This commit is contained in:
bptato
2024-10-20 18:15:39 +02:00
committed by GitHub
parent e69eb99a15
commit 67442471ae
9 changed files with 19 additions and 22 deletions

View File

@@ -1095,7 +1095,21 @@ proc setprotoent*(a1: cint) {.importc, header: "<netdb.h>".}
proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
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: "<poll.h>".} = culong
elif defined(zephyr):
type
Tnfds* = distinct cint
else:
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cuint
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {.
importc, header: "<poll.h>", sideEffect.}
proc realpath*(name, resolved: cstring): cstring {.

View File

@@ -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: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -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: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -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: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -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: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -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: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -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: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -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()

View File

@@ -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,