waitSignal() helper and tests for it. (#289)

* Add waitForSignal() implementation and tests.

* Fix compilation issues.

* Fix mistype.

* Rename to waitSignal().

* Fix Windows compilation issue.

* Re-export posix signals.

* Remove signal handler on continuation too.
This commit is contained in:
Eugene Kabanov 2022-06-29 00:53:09 +03:00 committed by GitHub
parent 84e32a3b69
commit 377e197417
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 8 deletions

View File

@ -174,7 +174,13 @@ when defined(windows):
elif unixPlatform:
import ./selectors2
from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
MSG_NOSIGNAL, SIGPIPE
MSG_NOSIGNAL
from posix import SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
SIGPIPE, SIGALRM, SIGTERM, SIGPIPE
export SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
SIGPIPE, SIGALRM, SIGTERM, SIGPIPE
type
CallbackFunc* = proc (arg: pointer) {.gcsafe, raises: [Defect].}
@ -851,6 +857,50 @@ proc callIdle*(cbproc: CallbackFunc) {.gcsafe, raises: [Defect].} =
include asyncfutures2
when not(defined(windows)):
when ioselSupportedPlatform:
proc waitSignal*(signal: int): Future[void] {.
raises: [Defect].} =
var retFuture = newFuture[void]("chronos.waitSignal()")
var sigfd: int = -1
template getSignalException(e: untyped): untyped =
newException(AsyncError, "Could not manipulate signal handler, " &
"reason [" & $e.name & "]: " & $e.msg)
proc continuation(udata: pointer) {.gcsafe.} =
if not(retFuture.finished()):
if sigfd != -1:
try:
removeSignal(sigfd)
retFuture.complete()
except IOSelectorsException as exc:
retFuture.fail(getSignalException(exc))
proc cancellation(udata: pointer) {.gcsafe.} =
if not(retFuture.finished()):
if sigfd != -1:
try:
removeSignal(sigfd)
except IOSelectorsException as exc:
retFuture.fail(getSignalException(exc))
sigfd =
try:
addSignal(signal, continuation)
except IOSelectorsException as exc:
retFuture.fail(getSignalException(exc))
return retFuture
except ValueError as exc:
retFuture.fail(getSignalException(exc))
return retFuture
except OSError as exc:
retFuture.fail(getSignalException(exc))
return retFuture
retFuture.cancelCallback = cancellation
retFuture
proc sleepAsync*(duration: Duration): Future[void] =
## Suspends the execution of the current async procedure for the next
## ``duration`` time.

View File

@ -38,13 +38,33 @@ suite "Signal handling test suite":
discard posix.kill(posix.getpid(), cint(signal))
waitFor(fut)
signalCounter == value
else:
const
SIGINT = 0
SIGTERM = 0
proc test(signal, value: int): bool = true
proc testWait(signal: int): bool =
var fut = waitSignal(signal)
discard posix.kill(posix.getpid(), cint(signal))
waitFor(fut)
true
test "SIGINT test":
check test(SIGINT, 31337) == true
when not defined(windows):
check test(SIGINT, 31337) == true
else:
skip()
test "SIGTERM test":
check test(SIGTERM, 65537) == true
when defined(windows):
skip()
else:
check test(SIGTERM, 65537) == true
test "waitSignal(SIGINT) test":
when defined(windows):
skip()
else:
check testWait(SIGINT) == true
test "waitSignal(SIGTERM) test":
when defined(windows):
skip()
else:
check testWait(SIGTERM) == true