Merge pull request #12371 from rayman22201/IOSelector_unregister_fix
Test + fix for epoll and kqueue selector modules to properly unregister event handles that have the key type "User"
This commit is contained in:
commit
6bfa4eb6c5
6 changed files with 33 additions and 7 deletions
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
## Library changes
|
## Library changes
|
||||||
|
|
||||||
|
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations` and only returns once all pending async operations are guaranteed to have completed.
|
||||||
|
- `asyncdispatch.drain` now consistently uses the passed timeout value for all iterations of the event loop, and not just the first iteration. This is more consistent with the other asyncdispatch apis, and allows `asyncdispatch.drain` to be more efficient.
|
||||||
- `base64.encode` and `base64.decode` was made faster by about 50%.
|
- `base64.encode` and `base64.decode` was made faster by about 50%.
|
||||||
- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support (ISO 40314).
|
- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support (ISO 40314).
|
||||||
|
|
||||||
|
|
@ -46,3 +48,4 @@
|
||||||
|
|
||||||
## Bugfixes
|
## Bugfixes
|
||||||
|
|
||||||
|
- The `FD` variant of `selector.unregister` for `ioselector_epoll` and `ioselector_select` now properly handle the `Event.User` select event type.
|
||||||
|
|
|
||||||
|
|
@ -1559,8 +1559,8 @@ proc drain*(timeout = 500) =
|
||||||
## Waits for completion events and processes them. Raises ``ValueError``
|
## Waits for completion events and processes them. Raises ``ValueError``
|
||||||
## if there are no pending operations. In contrast to ``poll`` this
|
## if there are no pending operations. In contrast to ``poll`` this
|
||||||
## processes as many events as are available.
|
## processes as many events as are available.
|
||||||
if runOnce(timeout):
|
if runOnce(timeout) or hasPendingOperations():
|
||||||
while hasPendingOperations() and runOnce(0): discard
|
while hasPendingOperations() and runOnce(timeout): discard
|
||||||
|
|
||||||
proc poll*(timeout = 500) =
|
proc poll*(timeout = 500) =
|
||||||
## Waits for completion events and processes them. Raises ``ValueError``
|
## Waits for completion events and processes them. Raises ``ValueError``
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
|
||||||
"Descriptor $# is not registered in the selector!" % $fdi)
|
"Descriptor $# is not registered in the selector!" % $fdi)
|
||||||
if pkey.events != {}:
|
if pkey.events != {}:
|
||||||
when not defined(android):
|
when not defined(android):
|
||||||
if pkey.events * {Event.Read, Event.Write} != {}:
|
if Event.Read in pkey.events or Event.Write in pkey.events or Event.User in pkey.events:
|
||||||
var epv = EpollEvent()
|
var epv = EpollEvent()
|
||||||
# TODO: Refactor all these EPOLL_CTL_DEL + dec(s.count) into a proc.
|
# TODO: Refactor all these EPOLL_CTL_DEL + dec(s.count) into a proc.
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
|
||||||
|
|
@ -237,7 +237,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) =
|
||||||
if posix.close(cint(fdi)) != 0:
|
if posix.close(cint(fdi)) != 0:
|
||||||
raiseIOSelectorsError(osLastError())
|
raiseIOSelectorsError(osLastError())
|
||||||
else:
|
else:
|
||||||
if pkey.events * {Event.Read, Event.Write} != {}:
|
if Event.Read in pkey.events or Event.Write in pkey.events or Event.User in pkey.events:
|
||||||
var epv = EpollEvent()
|
var epv = EpollEvent()
|
||||||
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
|
if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0:
|
||||||
raiseIOSelectorsError(osLastError())
|
raiseIOSelectorsError(osLastError())
|
||||||
|
|
|
||||||
|
|
@ -632,4 +632,4 @@ template withData*[T](s: Selector[T], fd: SocketHandle|int, value, body1,
|
||||||
|
|
||||||
|
|
||||||
proc getFd*[T](s: Selector[T]): int =
|
proc getFd*[T](s: Selector[T]): int =
|
||||||
return s.kqFD.int
|
return s.kqFD.int
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ proc unregister*[T](s: Selector[T], fd: SocketHandle|int) =
|
||||||
s.withSelectLock():
|
s.withSelectLock():
|
||||||
let fd = fd.SocketHandle
|
let fd = fd.SocketHandle
|
||||||
var pkey = s.getKey(fd)
|
var pkey = s.getKey(fd)
|
||||||
if Event.Read in pkey.events:
|
if Event.Read in pkey.events or Event.User in pkey.events:
|
||||||
IOFD_CLR(fd, addr s.rSet)
|
IOFD_CLR(fd, addr s.rSet)
|
||||||
dec(s.count)
|
dec(s.count)
|
||||||
if Event.Write in pkey.events:
|
if Event.Write in pkey.events:
|
||||||
|
|
@ -462,4 +462,4 @@ template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
|
||||||
|
|
||||||
|
|
||||||
proc getFd*[T](s: Selector[T]): int =
|
proc getFd*[T](s: Selector[T]): int =
|
||||||
return -1
|
return -1
|
||||||
|
|
|
||||||
23
tests/async/testmanyasyncevents.nim
Normal file
23
tests/async/testmanyasyncevents.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
hasPendingOperations: false
|
||||||
|
triggerCount: 100
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncDispatch
|
||||||
|
|
||||||
|
var triggerCount = 0
|
||||||
|
var evs = newSeq[AsyncEvent]()
|
||||||
|
|
||||||
|
for i in 0 ..< 100: # has to be lower than the typical physical fd limit
|
||||||
|
var ev = newAsyncEvent()
|
||||||
|
evs.add(ev)
|
||||||
|
addEvent(ev, proc(fd: AsyncFD): bool {.gcsafe,closure.} = triggerCount += 1; true)
|
||||||
|
|
||||||
|
for ev in evs:
|
||||||
|
ev.trigger()
|
||||||
|
|
||||||
|
drain()
|
||||||
|
echo "hasPendingOperations: ", hasPendingOperations()
|
||||||
|
echo "triggerCount: ", triggerCount
|
||||||
Loading…
Add table
Add a link
Reference in a new issue