From a6169d032c7bc4b7a903d6e96f6b2ccb32d9eb14 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Sun, 5 Jun 2016 15:32:48 +0100 Subject: [PATCH] OpenBSD: use __thrsigdivert as a replacement for sigtimedwait. --- src/dasync/dasync-kqueue.h | 63 ++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/dasync/dasync-kqueue.h b/src/dasync/dasync-kqueue.h index e7b33a4..0ccbc58 100644 --- a/src/dasync/dasync-kqueue.h +++ b/src/dasync/dasync-kqueue.h @@ -4,6 +4,14 @@ #include #include +#ifdef __OpenBSD__ +#include // for __thrsigdivert aka sigtimedwait +#include +extern "C" { + int __thrsigdivert(sigset_t set, siginfo_t *info, const struct timespec * timeout); +} +#endif + #include #include #include @@ -67,10 +75,19 @@ class KqueueTraits }; }; +#if defined(__OpenBSD__) +// OpenBSD has no sigtimedwait (or sigwaitinfo) but does have +// "__thrsigdivert" - WTF. +static inline int sigtimedwait(const sigset_t *ssp, siginfo_t *info, const struct timespec *timeout) +{ + // return __syscall(SYS___thrsigdivert, *ssp, info, timeout); + return __thrsigdivert(*ssp, info, timeout); +} +#endif template class KqueueLoop : public Base { - int kqfd; // epoll fd + int kqfd; // kqueue fd // Base contains: // lock - a lock that can be used to protect internal structure. @@ -87,19 +104,36 @@ template class KqueueLoop : public Base for (int i = 0; i < r; i++) { if (events[i].filter = EVFILT_SIGNAL) { - siginfo_t siginfo; + SigInfo siginfo; + //siginfo_t siginfo; sigset_t sset; sigemptyset(&sset); sigaddset(&sset, events[i].ident); - //int r = sigwaitinfo(&sset, &siginfo); - // OpenBSD doesn't have sigwaitinfo... - int r = 0; - if (r > 0) { - Base::receiveSignal(siginfo, (void *)events[i].udata); + struct timespec timeout; + timeout.tv_sec = 0; + timeout.tv_nsec = 0; + if (sigtimedwait(&sset, &siginfo.info, &timeout) > 0) { + Base::receiveSignal(siginfo, (void *)events[i].udata); } + // OpenBSD doesn't have sigwaitinfo... + // TODO we can probably do better by establishing a handler + // and letting it run (using eg sigsuspend()) but that requires + // a global area for returning the siginfo_t data and that in + // turn requires a global mutex. :( + //sigset_t sigset; + //sigpending(&sigset); + //SigInfo siginfo; + //if (sigismember(&sigset, events[i].ident)) { + // consume signal + // int rsig; + // sigemptyset(&sigset); + // sigaddset(&sigset, events[i].ident); + // sigwait(&sigset, &rsig); + // siginfo.info.si_signo = events[i].ident; + // Base::receiveSignal(siginfo, (void *)events[i].udata); + //} } - //else { // int flags = 0; // (events[i].events & EPOLLIN) && (flags |= in_events); @@ -120,19 +154,16 @@ template class KqueueLoop : public Base */ KqueueLoop() { - //epfd = epoll_create1(EPOLL_CLOEXEC); - //if (epfd == -1) { - // throw std::system_error(errno, std::system_category()); - //} + kqfd = kqueue(); + if (kqfd == -1) { + throw std::system_error(errno, std::system_category()); + } //sigemptyset(&sigmask); } ~KqueueLoop() { - //close(epfd); - //if (sigfd != -1) { - // close(sigfd); - //} + close(kqfd); } // flags: in_events | out_events -- 2.25.1