Recover `poll` engine and add tests. (#421)

* Initial commit.

* Fix one more place with deprecated constant.

* Fix testall and nimble file.

* Fix poll issue.

* Workaround Nim's faulty declaration of `poll()` and types on MacOS.

* Fix syntax errors.

* Fix MacOS post-rebase issue.

* Add more conditionals.

* Address review comments.

* Fix Nim 1.2 configuration defaults.
This commit is contained in:
Eugene Kabanov 2023-08-01 12:56:08 +03:00 committed by GitHub
parent 5c39bf47be
commit 6b4f5a1d23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 146 additions and 76 deletions

View File

@ -5,6 +5,5 @@
# Licensed under either of # Licensed under either of
# Apache License, version 2.0, (LICENSE-APACHEv2) # Apache License, version 2.0, (LICENSE-APACHEv2)
# MIT license (LICENSE-MIT) # MIT license (LICENSE-MIT)
import chronos/[asyncloop, asyncsync, handles, transport, timer, import chronos/[asyncloop, asyncsync, handles, transport, timer, debugutils]
asyncproc, debugutils] export asyncloop, asyncsync, handles, transport, timer, debugutils
export asyncloop, asyncsync, handles, transport, timer, asyncproc, debugutils

View File

@ -17,6 +17,22 @@ let nimc = getEnv("NIMC", "nim") # Which nim compiler to use
let lang = getEnv("NIMLANG", "c") # Which backend (c/cpp/js) let lang = getEnv("NIMLANG", "c") # Which backend (c/cpp/js)
let flags = getEnv("NIMFLAGS", "") # Extra flags for the compiler let flags = getEnv("NIMFLAGS", "") # Extra flags for the compiler
let verbose = getEnv("V", "") notin ["", "0"] let verbose = getEnv("V", "") notin ["", "0"]
let testArguments =
when defined(windows):
[
"-d:debug -d:chronosDebug -d:useSysAssert -d:useGcAssert",
"-d:debug -d:chronosPreviewV4",
"-d:release",
"-d:release -d:chronosPreviewV4"
]
else:
[
"-d:debug -d:chronosDebug -d:useSysAssert -d:useGcAssert",
"-d:debug -d:chronosPreviewV4",
"-d:debug -d:chronosDebug -d:chronosEventEngine=poll -d:useSysAssert -d:useGcAssert",
"-d:release",
"-d:release -d:chronosPreviewV4"
]
let styleCheckStyle = if (NimMajor, NimMinor) < (1, 6): "hint" else: "error" let styleCheckStyle = if (NimMajor, NimMinor) < (1, 6): "hint" else: "error"
let cfg = let cfg =
@ -31,12 +47,7 @@ proc run(args, path: string) =
build args & " -r", path build args & " -r", path
task test, "Run all tests": task test, "Run all tests":
for args in [ for args in testArguments:
"-d:debug -d:chronosDebug",
"-d:debug -d:chronosPreviewV4",
"-d:debug -d:chronosDebug -d:useSysAssert -d:useGcAssert",
"-d:release",
"-d:release -d:chronosPreviewV4"]:
run args, "tests/testall" run args, "tests/testall"
if (NimMajor, NimMinor) > (1, 6): if (NimMajor, NimMinor) > (1, 6):
run args & " --mm:refc", "tests/testall" run args & " --mm:refc", "tests/testall"

View File

@ -825,9 +825,9 @@ elif defined(macosx) or defined(freebsd) or defined(netbsd) or
var res = PDispatcher( var res = PDispatcher(
selector: selector, selector: selector,
timers: initHeapQueue[TimerCallback](), timers: initHeapQueue[TimerCallback](),
callbacks: initDeque[AsyncCallback](asyncEventsCount), callbacks: initDeque[AsyncCallback](chronosEventsCount),
idlers: initDeque[AsyncCallback](), idlers: initDeque[AsyncCallback](),
keys: newSeq[ReadyKey](asyncEventsCount), keys: newSeq[ReadyKey](chronosEventsCount),
trackers: initTable[string, TrackerBase](), trackers: initTable[string, TrackerBase](),
counters: initTable[string, TrackerCounter]() counters: initTable[string, TrackerCounter]()
) )
@ -1009,7 +1009,7 @@ elif defined(macosx) or defined(freebsd) or defined(netbsd) or
## You can execute ``aftercb`` before actual socket close operation. ## You can execute ``aftercb`` before actual socket close operation.
closeSocket(fd, aftercb) closeSocket(fd, aftercb)
when asyncEventEngine in ["epoll", "kqueue"]: when chronosEventEngine in ["epoll", "kqueue"]:
type type
ProcessHandle* = distinct int ProcessHandle* = distinct int
SignalHandle* = distinct int SignalHandle* = distinct int
@ -1123,7 +1123,7 @@ elif defined(macosx) or defined(freebsd) or defined(netbsd) or
if not isNil(adata.reader.function): if not isNil(adata.reader.function):
loop.callbacks.addLast(adata.reader) loop.callbacks.addLast(adata.reader)
when asyncEventEngine in ["epoll", "kqueue"]: when chronosEventEngine in ["epoll", "kqueue"]:
let customSet = {Event.Timer, Event.Signal, Event.Process, let customSet = {Event.Timer, Event.Signal, Event.Process,
Event.Vnode} Event.Vnode}
if customSet * events != {}: if customSet * events != {}:
@ -1257,10 +1257,7 @@ proc callIdle*(cbproc: CallbackFunc) =
include asyncfutures2 include asyncfutures2
when (chronosEventEngine in ["epoll", "kqueue"]) or defined(windows):
when defined(macosx) or defined(macos) or defined(freebsd) or
defined(netbsd) or defined(openbsd) or defined(dragonfly) or
defined(linux) or defined(windows):
proc waitSignal*(signal: int): Future[void] {.raises: [].} = proc waitSignal*(signal: int): Future[void] {.raises: [].} =
var retFuture = newFuture[void]("chronos.waitSignal()") var retFuture = newFuture[void]("chronos.waitSignal()")

View File

@ -49,6 +49,27 @@ when (NimMajor, NimMinor) >= (1, 4):
## using `AsyncProcessOption.EvalCommand` and API calls such as ## using `AsyncProcessOption.EvalCommand` and API calls such as
## ``execCommand(command)`` and ``execCommandEx(command)``. ## ``execCommand(command)`` and ``execCommandEx(command)``.
chronosEventsCount* {.intdefine.} = 64
## Number of OS poll events retrieved by syscall (epoll, kqueue, poll).
chronosInitialSize* {.intdefine.} = 64
## Initial size of Selector[T]'s array of file descriptors.
chronosEventEngine* {.strdefine.}: string =
when defined(linux) and not(defined(android) or defined(emscripten)):
"epoll"
elif defined(macosx) or defined(macos) or defined(ios) or
defined(freebsd) or defined(netbsd) or defined(openbsd) or
defined(dragonfly):
"kqueue"
elif defined(android) or defined(emscripten):
"poll"
elif defined(posix):
"poll"
else:
""
## OS polling engine type which is going to be used by chronos.
else: else:
# 1.2 doesn't support `booldefine` in `when` properly # 1.2 doesn't support `booldefine` in `when` properly
const const
@ -69,6 +90,21 @@ else:
"/system/bin/sh" "/system/bin/sh"
else: else:
"/bin/sh" "/bin/sh"
chronosEventsCount*: int = 64
chronosInitialSize*: int = 64
chronosEventEngine* {.strdefine.}: string =
when defined(linux) and not(defined(android) or defined(emscripten)):
"epoll"
elif defined(macosx) or defined(macos) or defined(ios) or
defined(freebsd) or defined(netbsd) or defined(openbsd) or
defined(dragonfly):
"kqueue"
elif defined(android) or defined(emscripten):
"poll"
elif defined(posix):
"poll"
else:
""
when defined(debug) or defined(chronosConfig): when defined(debug) or defined(chronosConfig):
import std/macros import std/macros
@ -83,3 +119,6 @@ when defined(debug) or defined(chronosConfig):
printOption("chronosFutureTracking", chronosFutureTracking) printOption("chronosFutureTracking", chronosFutureTracking)
printOption("chronosDumpAsync", chronosDumpAsync) printOption("chronosDumpAsync", chronosDumpAsync)
printOption("chronosProcShell", chronosProcShell) printOption("chronosProcShell", chronosProcShell)
printOption("chronosEventEngine", chronosEventEngine)
printOption("chronosEventsCount", chronosEventsCount)
printOption("chronosInitialSize", chronosInitialSize)

View File

@ -97,12 +97,12 @@ proc new*(t: typedesc[Selector], T: typedesc): SelectResult[Selector[T]] =
var nmask: Sigset var nmask: Sigset
if sigemptyset(nmask) < 0: if sigemptyset(nmask) < 0:
return err(osLastError()) return err(osLastError())
let epollFd = epoll_create(asyncEventsCount) let epollFd = epoll_create(chronosEventsCount)
if epollFd < 0: if epollFd < 0:
return err(osLastError()) return err(osLastError())
let selector = Selector[T]( let selector = Selector[T](
epollFd: epollFd, epollFd: epollFd,
fds: initTable[int32, SelectorKey[T]](asyncInitialSize), fds: initTable[int32, SelectorKey[T]](chronosInitialSize),
signalMask: nmask, signalMask: nmask,
virtualId: -1'i32, # Should start with -1, because `InvalidIdent` == -1 virtualId: -1'i32, # Should start with -1, because `InvalidIdent` == -1
childrenExited: false, childrenExited: false,
@ -627,7 +627,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
readyKeys: var openArray[ReadyKey] readyKeys: var openArray[ReadyKey]
): SelectResult[int] = ): SelectResult[int] =
var var
queueEvents: array[asyncEventsCount, EpollEvent] queueEvents: array[chronosEventsCount, EpollEvent]
k: int = 0 k: int = 0
verifySelectParams(timeout, -1, int(high(cint))) verifySelectParams(timeout, -1, int(high(cint)))
@ -668,7 +668,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
ok(k) ok(k)
proc select2*[T](s: Selector[T], timeout: int): SelectResult[seq[ReadyKey]] = proc select2*[T](s: Selector[T], timeout: int): SelectResult[seq[ReadyKey]] =
var res = newSeq[ReadyKey](asyncEventsCount) var res = newSeq[ReadyKey](chronosEventsCount)
let count = ? selectInto2(s, timeout, res) let count = ? selectInto2(s, timeout, res)
res.setLen(count) res.setLen(count)
ok(res) ok(res)

View File

@ -110,7 +110,7 @@ proc new*(t: typedesc[Selector], T: typedesc): SelectResult[Selector[T]] =
let selector = Selector[T]( let selector = Selector[T](
kqFd: kqFd, kqFd: kqFd,
fds: initTable[int32, SelectorKey[T]](asyncInitialSize), fds: initTable[int32, SelectorKey[T]](chronosInitialSize),
virtualId: -1'i32, # Should start with -1, because `InvalidIdent` == -1 virtualId: -1'i32, # Should start with -1, because `InvalidIdent` == -1
virtualHoles: initDeque[int32]() virtualHoles: initDeque[int32]()
) )
@ -559,7 +559,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
): SelectResult[int] = ): SelectResult[int] =
var var
tv: Timespec tv: Timespec
queueEvents: array[asyncEventsCount, KEvent] queueEvents: array[chronosEventsCount, KEvent]
verifySelectParams(timeout, -1, high(int)) verifySelectParams(timeout, -1, high(int))
@ -575,7 +575,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
addr tv addr tv
else: else:
nil nil
maxEventsCount = cint(min(asyncEventsCount, len(readyKeys))) maxEventsCount = cint(min(chronosEventsCount, len(readyKeys)))
eventsCount = eventsCount =
block: block:
var res = 0 var res = 0
@ -601,7 +601,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
proc select2*[T](s: Selector[T], proc select2*[T](s: Selector[T],
timeout: int): Result[seq[ReadyKey], OSErrorCode] = timeout: int): Result[seq[ReadyKey], OSErrorCode] =
var res = newSeq[ReadyKey](asyncEventsCount) var res = newSeq[ReadyKey](chronosEventsCount)
let count = ? selectInto2(s, timeout, res) let count = ? selectInto2(s, timeout, res)
res.setLen(count) res.setLen(count)
ok(res) ok(res)

View File

@ -16,7 +16,7 @@ import stew/base10
type type
SelectorImpl[T] = object SelectorImpl[T] = object
fds: Table[int32, SelectorKey[T]] fds: Table[int32, SelectorKey[T]]
pollfds: seq[TPollFd] pollfds: seq[TPollfd]
Selector*[T] = ref SelectorImpl[T] Selector*[T] = ref SelectorImpl[T]
type type
@ -50,7 +50,7 @@ proc freeKey[T](s: Selector[T], key: int32) =
proc new*(t: typedesc[Selector], T: typedesc): SelectResult[Selector[T]] = proc new*(t: typedesc[Selector], T: typedesc): SelectResult[Selector[T]] =
let selector = Selector[T]( let selector = Selector[T](
fds: initTable[int32, SelectorKey[T]](asyncInitialSize) fds: initTable[int32, SelectorKey[T]](chronosInitialSize)
) )
ok(selector) ok(selector)
@ -72,7 +72,7 @@ proc trigger2*(event: SelectEvent): SelectResult[void] =
if res == -1: if res == -1:
err(osLastError()) err(osLastError())
elif res != sizeof(uint64): elif res != sizeof(uint64):
err(OSErrorCode(osdefs.EINVAL)) err(osdefs.EINVAL)
else: else:
ok() ok()
@ -98,13 +98,14 @@ template toPollEvents(events: set[Event]): cshort =
res res
template pollAdd[T](s: Selector[T], sock: cint, events: set[Event]) = template pollAdd[T](s: Selector[T], sock: cint, events: set[Event]) =
s.pollfds.add(TPollFd(fd: sock, events: toPollEvents(events), revents: 0)) s.pollfds.add(TPollfd(fd: sock, events: toPollEvents(events), revents: 0))
template pollUpdate[T](s: Selector[T], sock: cint, events: set[Event]) = template pollUpdate[T](s: Selector[T], sock: cint, events: set[Event]) =
var updated = false var updated = false
for mitem in s.pollfds.mitems(): for mitem in s.pollfds.mitems():
if mitem.fd == sock: if mitem.fd == sock:
mitem.events = toPollEvents(events) mitem.events = toPollEvents(events)
updated = true
break break
if not(updated): if not(updated):
raiseAssert "Descriptor [" & $sock & "] is not registered in the queue!" raiseAssert "Descriptor [" & $sock & "] is not registered in the queue!"
@ -177,7 +178,6 @@ proc unregister2*[T](s: Selector[T], event: SelectEvent): SelectResult[void] =
proc prepareKey[T](s: Selector[T], event: var TPollfd): Opt[ReadyKey] = proc prepareKey[T](s: Selector[T], event: var TPollfd): Opt[ReadyKey] =
let let
defaultKey = SelectorKey[T](ident: InvalidIdent)
fdi32 = int32(event.fd) fdi32 = int32(event.fd)
revents = event.revents revents = event.revents
@ -224,7 +224,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
eventsCount = eventsCount =
if maxEventsCount > 0: if maxEventsCount > 0:
let res = handleEintr(poll(addr(s.pollfds[0]), Tnfds(maxEventsCount), let res = handleEintr(poll(addr(s.pollfds[0]), Tnfds(maxEventsCount),
timeout)) cint(timeout)))
if res < 0: if res < 0:
return err(osLastError()) return err(osLastError())
res res
@ -241,7 +241,7 @@ proc selectInto2*[T](s: Selector[T], timeout: int,
ok(k) ok(k)
proc select2*[T](s: Selector[T], timeout: int): SelectResult[seq[ReadyKey]] = proc select2*[T](s: Selector[T], timeout: int): SelectResult[seq[ReadyKey]] =
var res = newSeq[ReadyKey](asyncEventsCount) var res = newSeq[ReadyKey](chronosEventsCount)
let count = ? selectInto2(s, timeout, res) let count = ? selectInto2(s, timeout, res)
res.setLen(count) res.setLen(count)
ok(res) ok(res)

View File

@ -880,7 +880,7 @@ elif defined(macos) or defined(macosx):
sigemptyset, sigaddset, sigismember, fcntl, accept, sigemptyset, sigaddset, sigismember, fcntl, accept,
pipe, write, signal, read, setsockopt, getsockopt, pipe, write, signal, read, setsockopt, getsockopt,
getcwd, chdir, waitpid, kill, select, pselect, getcwd, chdir, waitpid, kill, select, pselect,
socketpair, freeAddrInfo, socketpair, poll, freeAddrInfo,
Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr, Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr,
SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6, SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6,
Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet, Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet,
@ -905,7 +905,7 @@ elif defined(macos) or defined(macosx):
sigemptyset, sigaddset, sigismember, fcntl, accept, sigemptyset, sigaddset, sigismember, fcntl, accept,
pipe, write, signal, read, setsockopt, getsockopt, pipe, write, signal, read, setsockopt, getsockopt,
getcwd, chdir, waitpid, kill, select, pselect, getcwd, chdir, waitpid, kill, select, pselect,
socketpair, freeAddrInfo, socketpair, poll, freeAddrInfo,
Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr, Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr,
SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6, SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6,
Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet, Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet,
@ -929,6 +929,21 @@ elif defined(macos) or defined(macosx):
numer*: uint32 numer*: uint32
denom*: uint32 denom*: uint32
TPollfd* {.importc: "struct pollfd", pure, final,
header: "<poll.h>".} = object
fd*: cint
events*: cshort
revents*: cshort
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cuint
const
POLLIN* = 0x0001
POLLOUT* = 0x0004
POLLERR* = 0x0008
POLLHUP* = 0x0010
POLLNVAL* = 0x0020
proc posix_gettimeofday*(tp: var Timeval, unused: pointer = nil) {. proc posix_gettimeofday*(tp: var Timeval, unused: pointer = nil) {.
importc: "gettimeofday", header: "<sys/time.h>".} importc: "gettimeofday", header: "<sys/time.h>".}
@ -938,6 +953,9 @@ elif defined(macos) or defined(macosx):
proc mach_absolute_time*(): uint64 {. proc mach_absolute_time*(): uint64 {.
importc, header: "<mach/mach_time.h>".} importc, header: "<mach/mach_time.h>".}
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {.
importc, header: "<poll.h>", sideEffect.}
elif defined(linux): elif defined(linux):
from std/posix import close, shutdown, sigemptyset, sigaddset, sigismember, from std/posix import close, shutdown, sigemptyset, sigaddset, sigismember,
sigdelset, write, read, waitid, getaddrinfo, sigdelset, write, read, waitid, getaddrinfo,
@ -947,12 +965,12 @@ elif defined(linux):
unlink, listen, sendmsg, recvmsg, getpid, fcntl, unlink, listen, sendmsg, recvmsg, getpid, fcntl,
pthread_sigmask, sigprocmask, clock_gettime, signal, pthread_sigmask, sigprocmask, clock_gettime, signal,
getcwd, chdir, waitpid, kill, select, pselect, getcwd, chdir, waitpid, kill, select, pselect,
socketpair, freeAddrInfo, socketpair, poll, freeAddrInfo,
ClockId, Itimerspec, Timespec, Sigset, Time, Pid, Mode, ClockId, Itimerspec, Timespec, Sigset, Time, Pid, Mode,
SigInfo, Id, Tmsghdr, IOVec, RLimit, Timeval, TFdSet, SigInfo, Id, Tmsghdr, IOVec, RLimit, Timeval, TFdSet,
SockAddr, SockLen, Sockaddr_storage, Sockaddr_in, SockAddr, SockLen, Sockaddr_storage, Sockaddr_in,
Sockaddr_in6, Sockaddr_un, AddrInfo, SocketHandle, Sockaddr_in6, Sockaddr_un, AddrInfo, SocketHandle,
Suseconds, Suseconds, TPollfd, Tnfds,
FD_CLR, FD_ISSET, FD_SET, FD_ZERO, FD_CLR, FD_ISSET, FD_SET, FD_ZERO,
CLOCK_MONOTONIC, F_GETFL, F_SETFL, F_GETFD, F_SETFD, CLOCK_MONOTONIC, F_GETFL, F_SETFL, F_GETFD, F_SETFD,
FD_CLOEXEC, O_NONBLOCK, SIG_BLOCK, SIG_UNBLOCK, FD_CLOEXEC, O_NONBLOCK, SIG_BLOCK, SIG_UNBLOCK,
@ -961,6 +979,7 @@ elif defined(linux):
AF_INET, AF_INET6, AF_UNIX, SO_REUSEADDR, SO_REUSEPORT, AF_INET, AF_INET6, AF_UNIX, SO_REUSEADDR, SO_REUSEPORT,
SO_BROADCAST, IPPROTO_IP, IPV6_MULTICAST_HOPS, SO_BROADCAST, IPPROTO_IP, IPV6_MULTICAST_HOPS,
SOCK_DGRAM, SOCK_STREAM, SHUT_RD, SHUT_WR, SHUT_RDWR, SOCK_DGRAM, SOCK_STREAM, SHUT_RD, SHUT_WR, SHUT_RDWR,
POLLIN, POLLOUT, POLLERR, POLLHUP, POLLNVAL,
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP, SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP,
@ -974,12 +993,12 @@ elif defined(linux):
unlink, listen, sendmsg, recvmsg, getpid, fcntl, unlink, listen, sendmsg, recvmsg, getpid, fcntl,
pthread_sigmask, sigprocmask, clock_gettime, signal, pthread_sigmask, sigprocmask, clock_gettime, signal,
getcwd, chdir, waitpid, kill, select, pselect, getcwd, chdir, waitpid, kill, select, pselect,
socketpair, freeAddrInfo, socketpair, poll, freeAddrInfo,
ClockId, Itimerspec, Timespec, Sigset, Time, Pid, Mode, ClockId, Itimerspec, Timespec, Sigset, Time, Pid, Mode,
SigInfo, Id, Tmsghdr, IOVec, RLimit, TFdSet, Timeval, SigInfo, Id, Tmsghdr, IOVec, RLimit, TFdSet, Timeval,
SockAddr, SockLen, Sockaddr_storage, Sockaddr_in, SockAddr, SockLen, Sockaddr_storage, Sockaddr_in,
Sockaddr_in6, Sockaddr_un, AddrInfo, SocketHandle, Sockaddr_in6, Sockaddr_un, AddrInfo, SocketHandle,
Suseconds, Suseconds, TPollfd, Tnfds,
FD_CLR, FD_ISSET, FD_SET, FD_ZERO, FD_CLR, FD_ISSET, FD_SET, FD_ZERO,
CLOCK_MONOTONIC, F_GETFL, F_SETFL, F_GETFD, F_SETFD, CLOCK_MONOTONIC, F_GETFL, F_SETFL, F_GETFD, F_SETFD,
FD_CLOEXEC, O_NONBLOCK, SIG_BLOCK, SIG_UNBLOCK, FD_CLOEXEC, O_NONBLOCK, SIG_BLOCK, SIG_UNBLOCK,
@ -988,6 +1007,7 @@ elif defined(linux):
AF_INET, AF_INET6, AF_UNIX, SO_REUSEADDR, SO_REUSEPORT, AF_INET, AF_INET6, AF_UNIX, SO_REUSEADDR, SO_REUSEPORT,
SO_BROADCAST, IPPROTO_IP, IPV6_MULTICAST_HOPS, SO_BROADCAST, IPPROTO_IP, IPV6_MULTICAST_HOPS,
SOCK_DGRAM, SOCK_STREAM, SHUT_RD, SHUT_WR, SHUT_RDWR, SOCK_DGRAM, SOCK_STREAM, SHUT_RD, SHUT_WR, SHUT_RDWR,
POLLIN, POLLOUT, POLLERR, POLLHUP, POLLNVAL,
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP, SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP,
@ -1097,11 +1117,11 @@ elif defined(freebsd) or defined(openbsd) or defined(netbsd) or
sigaddset, sigismember, fcntl, accept, pipe, write, sigaddset, sigismember, fcntl, accept, pipe, write,
signal, read, setsockopt, getsockopt, clock_gettime, signal, read, setsockopt, getsockopt, clock_gettime,
getcwd, chdir, waitpid, kill, select, pselect, getcwd, chdir, waitpid, kill, select, pselect,
socketpair, freeAddrInfo, socketpair, poll, freeAddrInfo,
Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr, Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr,
SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6, SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6,
Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet, Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet,
Suseconds, Suseconds, TPollfd, Tnfds,
FD_CLR, FD_ISSET, FD_SET, FD_ZERO, FD_CLR, FD_ISSET, FD_SET, FD_ZERO,
F_GETFL, F_SETFL, F_GETFD, F_SETFD, FD_CLOEXEC, F_GETFL, F_SETFL, F_GETFD, F_SETFD, FD_CLOEXEC,
O_NONBLOCK, SOL_SOCKET, SOCK_RAW, SOCK_DGRAM, O_NONBLOCK, SOL_SOCKET, SOCK_RAW, SOCK_DGRAM,
@ -1111,6 +1131,7 @@ elif defined(freebsd) or defined(openbsd) or defined(netbsd) or
IPV6_MULTICAST_HOPS, SOCK_DGRAM, RLIMIT_NOFILE, IPV6_MULTICAST_HOPS, SOCK_DGRAM, RLIMIT_NOFILE,
SIG_BLOCK, SIG_UNBLOCK, CLOCK_MONOTONIC, SIG_BLOCK, SIG_UNBLOCK, CLOCK_MONOTONIC,
SHUT_RD, SHUT_WR, SHUT_RDWR, SHUT_RD, SHUT_WR, SHUT_RDWR,
POLLIN, POLLOUT, POLLERR, POLLHUP, POLLNVAL,
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP, SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP,
@ -1123,11 +1144,11 @@ elif defined(freebsd) or defined(openbsd) or defined(netbsd) or
sigaddset, sigismember, fcntl, accept, pipe, write, sigaddset, sigismember, fcntl, accept, pipe, write,
signal, read, setsockopt, getsockopt, clock_gettime, signal, read, setsockopt, getsockopt, clock_gettime,
getcwd, chdir, waitpid, kill, select, pselect, getcwd, chdir, waitpid, kill, select, pselect,
socketpair, freeAddrInfo, socketpair, poll, freeAddrInfo,
Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr, Timeval, Timespec, Pid, Mode, Time, Sigset, SockAddr,
SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6, SockLen, Sockaddr_storage, Sockaddr_in, Sockaddr_in6,
Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet, Sockaddr_un, SocketHandle, AddrInfo, RLimit, TFdSet,
Suseconds, Suseconds, TPollfd, Tnfds,
FD_CLR, FD_ISSET, FD_SET, FD_ZERO, FD_CLR, FD_ISSET, FD_SET, FD_ZERO,
F_GETFL, F_SETFL, F_GETFD, F_SETFD, FD_CLOEXEC, F_GETFL, F_SETFL, F_GETFD, F_SETFD, FD_CLOEXEC,
O_NONBLOCK, SOL_SOCKET, SOCK_RAW, SOCK_DGRAM, O_NONBLOCK, SOL_SOCKET, SOCK_RAW, SOCK_DGRAM,
@ -1137,6 +1158,7 @@ elif defined(freebsd) or defined(openbsd) or defined(netbsd) or
IPV6_MULTICAST_HOPS, SOCK_DGRAM, RLIMIT_NOFILE, IPV6_MULTICAST_HOPS, SOCK_DGRAM, RLIMIT_NOFILE,
SIG_BLOCK, SIG_UNBLOCK, CLOCK_MONOTONIC, SIG_BLOCK, SIG_UNBLOCK, CLOCK_MONOTONIC,
SHUT_RD, SHUT_WR, SHUT_RDWR, SHUT_RD, SHUT_WR, SHUT_RDWR,
POLLIN, POLLOUT, POLLERR, POLLHUP, POLLNVAL,
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP, SIGPIPE, SIGALRM, SIGTERM, SIGPIPE, SIGCHLD, SIGSTOP,

View File

@ -32,29 +32,9 @@
# backwards-compatible. # backwards-compatible.
import stew/results import stew/results
import osdefs, osutils, oserrno import config, osdefs, osutils, oserrno
export results, oserrno export results, oserrno
const
asyncEventsCount* {.intdefine.} = 64
## Number of epoll events retrieved by syscall.
asyncInitialSize* {.intdefine.} = 64
## Initial size of Selector[T]'s array of file descriptors.
asyncEventEngine* {.strdefine.} =
when defined(linux):
"epoll"
elif defined(macosx) or defined(macos) or defined(ios) or
defined(freebsd) or defined(netbsd) or defined(openbsd) or
defined(dragonfly):
"kqueue"
elif defined(posix):
"poll"
else:
""
## Engine type which is going to be used by module.
hasThreadSupport = compileOption("threads")
when defined(nimdoc): when defined(nimdoc):
type type
@ -281,7 +261,9 @@ else:
var err = newException(IOSelectorsException, msg) var err = newException(IOSelectorsException, msg)
raise err raise err
when asyncEventEngine in ["epoll", "kqueue"]: when chronosEventEngine in ["epoll", "kqueue"]:
const hasThreadSupport = compileOption("threads")
proc blockSignals(newmask: Sigset, proc blockSignals(newmask: Sigset,
oldmask: var Sigset): Result[void, OSErrorCode] = oldmask: var Sigset): Result[void, OSErrorCode] =
var nmask = newmask var nmask = newmask
@ -324,11 +306,11 @@ else:
doAssert((timeout >= min) and (timeout <= max), doAssert((timeout >= min) and (timeout <= max),
"Cannot select with incorrect timeout value, got " & $timeout) "Cannot select with incorrect timeout value, got " & $timeout)
when asyncEventEngine == "epoll": when chronosEventEngine == "epoll":
include ./ioselects/ioselectors_epoll include ./ioselects/ioselectors_epoll
elif asyncEventEngine == "kqueue": elif chronosEventEngine == "kqueue":
include ./ioselects/ioselectors_kqueue include ./ioselects/ioselectors_kqueue
elif asyncEventEngine == "poll": elif chronosEventEngine == "poll":
include ./ioselects/ioselectors_poll include ./ioselects/ioselectors_poll
else: else:
{.fatal: "Event engine `" & asyncEventEngine & "` is not supported!".} {.fatal: "Event engine `" & chronosEventEngine & "` is not supported!".}

View File

@ -38,8 +38,12 @@ when defined(nimdoc):
## be prepared to retry the call if there were unsent bytes. ## be prepared to retry the call if there were unsent bytes.
## ##
## On error, ``-1`` is returned. ## On error, ``-1`` is returned.
elif defined(emscripten):
elif defined(linux) or defined(android): proc sendfile*(outfd, infd: int, offset: int, count: var int): int =
raiseAssert "sendfile() is not implemented yet"
elif (defined(linux) or defined(android)) and not(defined(emscripten)):
proc osSendFile*(outfd, infd: cint, offset: ptr int, count: int): int proc osSendFile*(outfd, infd: cint, offset: ptr int, count: int): int
{.importc: "sendfile", header: "<sys/sendfile.h>".} {.importc: "sendfile", header: "<sys/sendfile.h>".}

View File

@ -5,10 +5,22 @@
# Licensed under either of # Licensed under either of
# Apache License, version 2.0, (LICENSE-APACHEv2) # Apache License, version 2.0, (LICENSE-APACHEv2)
# MIT license (LICENSE-MIT) # MIT license (LICENSE-MIT)
import testmacro, testsync, testsoon, testtime, testfut, testsignal, import ".."/chronos/config
testaddress, testdatagram, teststream, testserver, testbugs, testnet,
testasyncstream, testhttpserver, testshttpserver, testhttpclient,
testproc, testratelimit, testfutures, testthreadsync
# Must be imported last to check for Pending futures when (chronosEventEngine in ["epoll", "kqueue"]) or defined(windows):
import testutils import testmacro, testsync, testsoon, testtime, testfut, testsignal,
testaddress, testdatagram, teststream, testserver, testbugs, testnet,
testasyncstream, testhttpserver, testshttpserver, testhttpclient,
testproc, testratelimit, testfutures, testthreadsync
# Must be imported last to check for Pending futures
import testutils
elif chronosEventEngine == "poll":
# `poll` engine do not support signals and processes
import testmacro, testsync, testsoon, testtime, testfut, testaddress,
testdatagram, teststream, testserver, testbugs, testnet,
testasyncstream, testhttpserver, testshttpserver, testhttpclient,
testratelimit, testfutures, testthreadsync
# Must be imported last to check for Pending futures
import testutils

View File

@ -8,6 +8,7 @@
import std/os import std/os
import stew/[base10, byteutils] import stew/[base10, byteutils]
import ".."/chronos/unittest2/asynctests import ".."/chronos/unittest2/asynctests
import ".."/chronos/asyncproc
when defined(posix): when defined(posix):
from ".."/chronos/osdefs import SIGKILL from ".."/chronos/osdefs import SIGKILL

View File

@ -1339,7 +1339,10 @@ suite "Stream Transport test suite":
else: else:
skip() skip()
else: else:
check waitFor(testSendFile(addresses[i])) == FilesCount if defined(emscripten):
skip()
else:
check waitFor(testSendFile(addresses[i])) == FilesCount
test prefixes[i] & "Connection refused test": test prefixes[i] & "Connection refused test":
var address: TransportAddress var address: TransportAddress
if addresses[i].family == AddressFamily.Unix: if addresses[i].family == AddressFamily.Unix: