Add asynchronous posix signal handling.

Add signal tests.
This commit is contained in:
cheatfate 2018-05-25 04:05:13 +03:00
parent d75487948b
commit a4528ab705
3 changed files with 72 additions and 9 deletions

View File

@ -26,6 +26,10 @@ task test, "Run all tests":
exec "nim c -r tests/testfut"
exec "nim c -r -d:release tests/testfut"
exec "nim c -r -d:useSysAssert -d:useGcAssert tests/testsignal"
exec "nim c -r tests/testsignal"
exec "nim c -r -d:release tests/testsignal"
exec "nim c -r -d:useSysAssert -d:useGcAssert tests/testdatagram"
exec "nim c -r tests/testdatagram"
exec "nim c -r -d:release tests/testdatagram"

View File

@ -185,6 +185,7 @@ proc initCallSoonProc() =
when defined(windows) or defined(nimdoc):
import winlean, sets, hashes
type
WSAPROC_TRANSMITFILE = proc(hSocket: SocketHandle, hFile: Handle,
nNumberOfBytesToWrite: DWORD,
@ -203,6 +204,9 @@ when defined(windows) or defined(nimdoc):
bytesCount*: int32
udata*: pointer
CustomOverlapped* = object of OVERLAPPED
data*: CompletionData
PDispatcher* = ref object of PDispatcherBase
ioPort: Handle
handles: HashSet[AsyncFD]
@ -211,9 +215,6 @@ when defined(windows) or defined(nimdoc):
getAcceptExSockAddrs*: WSAPROC_GETACCEPTEXSOCKADDRS
transmitFile*: WSAPROC_TRANSMITFILE
CustomOverlapped* = object of OVERLAPPED
data*: CompletionData
PtrCustomOverlapped* = ptr CustomOverlapped
RefCustomOverlapped* = ref CustomOverlapped
@ -324,12 +325,6 @@ when defined(windows) or defined(nimdoc):
var callable = loop.callbacks.popFirst()
callable.function(callable.udata)
template getUdata*(u: untyped) =
if isNil(u):
nil
else:
cast[ptr CustomOverlapped](u).data.udata
proc getFunc(s: SocketHandle, fun: var pointer, guid: var GUID): bool =
var bytesRet: Dword
fun = nil
@ -497,6 +492,27 @@ else:
raise newException(ValueError, "File descriptor not registered.")
p.selector.updateHandle(int(fd), newEvents)
when ioselSupportedPlatform:
proc addSignal*(signal: int, cb: CallbackFunc,
udata: pointer = nil): int =
## Start watching signal ``signal``, and when signal appears, call the
## callback ``cb``. Returns signal identifier code, which can be used
## to remove signal callback via ``removeSignal``.
let p = getGlobalDispatcher()
var data: SelectorData
result = p.selector.registerSignal(signal, data)
withData(p.selector, result, adata) do:
adata.reader = AsyncCallback(function: cb, udata: addr adata.rdata)
adata.rdata.fd = AsyncFD(result)
adata.rdata.udata = udata
do:
raise newException(ValueError, "File descriptor not registered.")
proc removeSignal*(sigfd: int) =
## Remove watching signal ``signal``.
let p = getGlobalDispatcher()
p.selector.unregister(sigfd)
proc poll*() =
let loop = getGlobalDispatcher()
var curTime = fastEpochTime()

43
tests/testsignal.nim Normal file
View File

@ -0,0 +1,43 @@
# Asyncdispatch2 Test Suite
# (c) Copyright 2018
# Status Research & Development GmbH
#
# Licensed under either of
# Apache License, version 2.0, (LICENSE-APACHEv2)
# MIT license (LICENSE-MIT)
import unittest, strutils
import ../asyncdispatch2
when not defined(windows):
import posix
var signalCounter = 0
proc signalProc(udata: pointer) =
var cdata = cast[ptr CompletionData](udata)
signalCounter = cast[int](cdata.udata)
removeSignal(int(cdata.fd))
proc asyncProc() {.async.} =
await sleepAsync(500)
proc test(signal, value: int): bool =
discard addSignal(signal, signalProc, cast[pointer](value))
var fut = asyncProc()
discard posix.kill(posix.getpid(), cint(signal))
waitFor(fut)
signalCounter == value
else:
const
SIGINT = 0
SIGTERM = 0
proc test(signal, value: int): bool = true
when isMainModule:
suite "Signal handling test suite":
test "SIGINT test":
check test(SIGINT, 31337) == true
test "SIGTERM test":
check test(SIGTERM, 65537) == true