Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion chronos/internal/asyncengine.nim
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ when defined(nimdoc):
## Perform single asynchronous step, processing timers and completing
## tasks. Blocks until at least one event has completed.
##
## Exceptions raised during `async` task exection are stored as outcome
## Exceptions raised during `async` task exception are stored as outcome
## in the corresponding `Future` - `poll` itself does not raise.

proc register2*(fd: AsyncFD): Result[void, OSErrorCode] = discard
Expand Down Expand Up @@ -697,6 +697,19 @@ elif defined(windows):
if not(isNil(aftercb)):
loop.callbacks.addLast(AsyncCallback(function: aftercb, udata: param))

proc safeCloseHandle(h: HANDLE): Result[void, string] =
let res = closeHandle(h)
if res == 0: # WINBOOL FALSE
return err("Failed to close handle error code: " & osErrorMsg(osLastError()))
ok()

proc closeDispatcher*(loop: PDispatcher): Result[void, string] =
? safeCloseHandle(loop.ioPort)
for i in loop.handles.items:
closeHandle(i)
loop.handles.clear()
ok()

proc unregisterAndCloseFd*(fd: AsyncFD): Result[void, OSErrorCode] =
## Unregister from system queue and close asynchronous socket.
##
Expand Down Expand Up @@ -936,6 +949,14 @@ elif defined(macosx) or defined(freebsd) or defined(netbsd) or
## You can execute ``aftercb`` before actual socket close operation.
closeSocket(fd, aftercb)

proc closeDispatcher*(loop: PDispatcher): Result[void, string] =
## Close selector associated with current thread's dispatcher.
try:
loop.selector.close()
except IOSelectorsException as e:
return err("Exception in closeDispatcher: " & e.msg)
ok()

when chronosEventEngine in ["epoll", "kqueue"]:
type
ProcessHandle* = distinct int
Expand Down
11 changes: 11 additions & 0 deletions chronos/internal/asyncfutures.nim
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,17 @@ proc pollFor[F: Future | InternalRaisesFuture](fut: F): F {.raises: [].} =

fut

proc shutdown*(): Result[void, string] {.raises: [].} =
## Performs the shutdown and cleanup of all dispatcher resources.
## Notice that this should be called only when sure that no new async tasks will be scheduled.
##
## This routine shall be called only after `pollFor` has completed. Upon
## invocation, all streams are assumed to have been closed.

let disp = getThreadDispatcher()
? disp.closeDispatcher()
ok()

proc waitFor*[T: not void](fut: Future[T]): lent T {.raises: [CatchableError].} =
## Blocks the current thread of execution until `fut` has finished, returning
## its value.
Expand Down
2 changes: 1 addition & 1 deletion chronos/ioselects/ioselectors_poll.nim
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ proc new*(t: typedesc[Selector], T: typedesc): SelectResult[Selector[T]] =

proc close2*[T](s: Selector[T]): SelectResult[void] =
s.fds.clear()
s.pollfds.clear()
s.pollfds.setLen(0)

proc new*(t: typedesc[SelectEvent]): SelectResult[SelectEvent] =
let flags = {DescriptorFlag.NonBlock, DescriptorFlag.CloseOnExec}
Expand Down