From 5fed950925d276b7c70c7be30a56ed3d86cc74dd Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Thu, 16 Jun 2016 08:27:22 +0100 Subject: [PATCH] Update dasynq to latest HEAD --- src/dasync/dasync-childproc.h | 16 ++++++ src/dasync/dasync-epoll.h | 12 ++-- src/dasync/dasync-kqueue.h | 103 +++++++++++++--------------------- src/dasync/dasync.h | 32 +++++------ 4 files changed, 75 insertions(+), 88 deletions(-) diff --git a/src/dasync/dasync-childproc.h b/src/dasync/dasync-childproc.h index f92d4c6..990fbb1 100644 --- a/src/dasync/dasync-childproc.h +++ b/src/dasync/dasync-childproc.h @@ -74,6 +74,17 @@ class pid_map } }; +namespace { + void sigchld_handler(int signum) + { + // If SIGCHLD has no handler (is ignored), SIGCHLD signals will + // not be queued for terminated child processes. (On Linux, the + // default disposition for SIGCHLD is to be ignored but *not* have + // this behavior, which seems inconsistent. Setting a handler doesn't + // hurt in any case). + } +} + template class ChildProcEvents : public Base { private: @@ -118,6 +129,11 @@ template class ChildProcEvents : public Base template void init(T *loop_mech) { loop_mech->addSignalWatch(SIGCHLD, nullptr); + struct sigaction chld_action; + chld_action.sa_handler = sigchld_handler; + sigemptyset(&chld_action.sa_mask); + chld_action.sa_flags = 0; + sigaction(SIGCHLD, &chld_action, nullptr); } }; diff --git a/src/dasync/dasync-epoll.h b/src/dasync/dasync-epoll.h index 5bd3e5e..05cf5aa 100644 --- a/src/dasync/dasync-epoll.h +++ b/src/dasync/dasync-epoll.h @@ -167,14 +167,14 @@ template class EpollLoop : public Base } } - void removeFdWatch(int fd) noexcept + void removeFdWatch(int fd, int flags) noexcept { epoll_ctl(epfd, EPOLL_CTL_DEL, fd, nullptr); } - void removeFdWatch_nolock(int fd) noexcept + void removeFdWatch_nolock(int fd, int flags) noexcept { - removeFdWatch(fd); + removeFdWatch(fd, flags); } // Note this will *replace* the old flags with the new, that is, @@ -207,7 +207,7 @@ template class EpollLoop : public Base enableFdWatch(fd, userdata, flags); } - void disableFdWatch(int fd) noexcept + void disableFdWatch(int fd, int flags) noexcept { struct epoll_event epevent; // epevent.data.fd = fd; @@ -223,9 +223,9 @@ template class EpollLoop : public Base } } - void disableFdWatch_nolock(int fd) noexcept + void disableFdWatch_nolock(int fd, int flags) noexcept { - disableFdWatch(fd); + disableFdWatch(fd, flags); } // Note signal should be masked before call. diff --git a/src/dasync/dasync-kqueue.h b/src/dasync/dasync-kqueue.h index 5dab0c5..fb6d9da 100644 --- a/src/dasync/dasync-kqueue.h +++ b/src/dasync/dasync-kqueue.h @@ -64,6 +64,9 @@ class KqueueTraits { return fd; } + FD_r(int nfd) : fd(nfd) + { + } }; const static bool has_separate_rw_fd_watches = true; @@ -139,13 +142,14 @@ template class KqueueLoop : public Base events[i].flags = EV_ENABLE; } } + else if (events[i].filter == EVFILT_READ || events[i].filter == EVFILT_WRITE) { + int flags = events[i].filter == EVFILT_READ ? in_events : out_events; + Base::receiveFdEvent(*this, FD_r(events[i].ident), events[i].udata, flags); + events[i].flags = EV_DISABLE | EV_CLEAR; + // we use EV_CLEAR to clear the EOF status of fifos/pipes (and wait for + // another connection). + } else { - // int flags = 0; - // (events[i].events & EPOLLIN) && (flags |= in_events); - // (events[i].events & EPOLLHUP) && (flags |= in_events); - // (events[i].events & EPOLLOUT) && (flags |= out_events); - // (events[i].events & EPOLLERR) && (flags |= err_events); - // Base::receiveFdEvent(*this, FD_r(), ptr, flags); events[i].flags = EV_DISABLE; } } @@ -176,68 +180,47 @@ template class KqueueLoop : public Base close(kqfd); } - void disableFilter(short filterType, uintptr_t ident) + void setFilterEnabled(short filterType, uintptr_t ident, bool enable) { struct kevent kev; - EV_SET(&kev, ident, filterType, EV_DISABLE, 0, 0, 0); + EV_SET(&kev, ident, filterType, enable ? EV_ENABLE : EV_DISABLE, 0, 0, 0); kevent(kqfd, &kev, 1, nullptr, 0, nullptr); } + void removeFilter(short filterType, uintptr_t ident) + { + struct kevent kev; + EV_SET(&kev, ident, filterType, EV_DELETE, 0, 0, 0); + kevent(kqfd, &kev, 1, nullptr, 0, nullptr); + } + // flags: in_events | out_events void addFdWatch(int fd, void *userdata, int flags) { - //struct epoll_event epevent; - // epevent.data.fd = fd; - //epevent.data.ptr = userdata; - //epevent.events = 0; + // TODO kqueue doesn't support EVFILE_WRITE on file fd's :/ - //if (flags & one_shot) { - // epevent.events = EPOLLONESHOT; - //} - //if (flags & in_events) { - // epevent.events |= EPOLLIN; - //} - //if (flags & out_events) { - // epevent.events |= EPOLLOUT; - //} - - //if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &epevent) == -1) { - // throw new std::system_error(errno, std::system_category()); - //} + short filter = (flags & in_events) ? EVFILT_READ : EVFILT_WRITE; + + struct kevent kev; + EV_SET(&kev, fd, filter, EV_ADD, 0, 0, userdata); + if (kevent(kqfd, &kev, 1, nullptr, 0, nullptr) == -1) { + throw new std::system_error(errno, std::system_category()); + } } - void removeFdWatch(int fd) - { - //epoll_ctl(epfd, EPOLL_CTL_DEL, fd, nullptr); + void removeFdWatch(int fd, int flags) + { + removeFilter((flags & in_events) ? EVFILT_READ : EVFILT_WRITE, fd); } - void removeFdWatch_nolock(int fd) + void removeFdWatch_nolock(int fd, int flags) { - removeFdWatch(fd); + removeFdWatch(fd, flags); } - // Note this will *replace* the old flags with the new, that is, - // it can enable *or disable* read/write events. void enableFdWatch(int fd, void *userdata, int flags) { - //struct epoll_event epevent; - // epevent.data.fd = fd; - //epevent.data.ptr = userdata; - //epevent.events = 0; - - //if (flags & one_shot) { - // epevent.events = EPOLLONESHOT; - //} - //if (flags & in_events) { - // epevent.events |= EPOLLIN; - //} - //if (flags & out_events) { - // epevent.events |= EPOLLOUT; - //} - - //if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &epevent) == -1) { - // throw new std::system_error(errno, std::system_category()); - //} + setFilterEnabled((flags & in_events) ? EVFILT_READ : EVFILT_WRITE, fd, true); } void enableFdWatch_nolock(int fd, void *userdata, int flags) @@ -245,24 +228,14 @@ template class KqueueLoop : public Base enableFdWatch(fd, userdata, flags); } - void disableFdWatch(int fd) + void disableFdWatch(int fd, int flags) { - //struct epoll_event epevent; - // epevent.data.fd = fd; - //epevent.data.ptr = nullptr; - //epevent.events = 0; - - // Epoll documentation says that hangup will still be reported, need to check - // whether this is really the case. Suspect it is really only the case if - // EPOLLIN is set. - //if (epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &epevent) == -1) { - // throw new std::system_error(errno, std::system_category()); - //} + setFilterEnabled((flags & in_events) ? EVFILT_READ : EVFILT_WRITE, fd, false); } - void disableFdWatch_nolock(int fd) + void disableFdWatch_nolock(int fd, int flags) { - // TODO + disableFdWatch(fd, flags); } // Note signal should be masked before call. @@ -345,7 +318,7 @@ template class KqueueLoop : public Base sigdelset(&sigmask, rsigno); // TODO accumulate and disable multiple filters with a single kevents call // rather than disabling each individually - disableFilter(EVFILT_SIGNAL, rsigno); + setFilterEnabled(EVFILT_SIGNAL, rsigno, false); } Base::receiveSignal(siginfo, sigdataMap[rsigno]); rsigno = sigtimedwait(&sigmask, &siginfo.info, &timeout); diff --git a/src/dasync/dasync.h b/src/dasync/dasync.h index 807f88e..3602f01 100644 --- a/src/dasync/dasync.h +++ b/src/dasync/dasync.h @@ -571,7 +571,7 @@ template class EventLoop loop_mech.removeSignalWatch(signo); waitqueue_node qnode; - getAttnLock(qnode); + getAttnLock(qnode); EventDispatch & ed = (EventDispatch &) loop_mech; ed.issueDelete(callBack); @@ -600,7 +600,7 @@ template class EventLoop loop_mech.enableFdWatch(fd, watcher, watch_flags | one_shot); } else { - loop_mech.disableFdWatch(fd); + loop_mech.disableFdWatch(fd, watch_flags); } } @@ -610,16 +610,16 @@ template class EventLoop loop_mech.enableFdWatch_nolock(fd, watcher, watch_flags | one_shot); } else { - loop_mech.disableFdWatch_nolock(fd); + loop_mech.disableFdWatch_nolock(fd, watch_flags); } } void deregister(BaseFdWatcher *callback, int fd) { - loop_mech.removeFdWatch(fd); + loop_mech.removeFdWatch(fd, callback->watch_flags); waitqueue_node qnode; - getAttnLock(qnode); + getAttnLock(qnode); EventDispatch & ed = (EventDispatch &) loop_mech; ed.issueDelete(callback); @@ -633,11 +633,11 @@ template class EventLoop // TODO } else { - loop_mech.removeFdWatch(fd); + loop_mech.removeFdWatch(fd, callback->watch_flags); } waitqueue_node qnode; - getAttnLock(qnode); + getAttnLock(qnode); EventDispatch & ed = (EventDispatch &) loop_mech; ed.issueDelete(callback); @@ -743,14 +743,14 @@ template class EventLoop } else { // both removed: actually remove - loop_mech.removeFdWatch_nolock(bdfw->watch_fd); + loop_mech.removeFdWatch_nolock(bdfw->watch_fd, 0 /* not used */); return Rearm::REMOVE; } } else { // TODO this will need flags for such a loop, since it can't // otherwise distinguish which channel watch to remove - loop_mech.removeFdWatch_nolock(bdfw->watch_fd); + loop_mech.removeFdWatch_nolock(bdfw->watch_fd, bdfw->watch_flags); } } else if (rearmType == Rearm::DISARM) { @@ -777,7 +777,7 @@ template class EventLoop (bfw->watch_flags & (in_events | out_events)) | one_shot); } else if (rearmType == Rearm::REMOVE) { - loop_mech.removeFdWatch_nolock(bfw->watch_fd); + loop_mech.removeFdWatch_nolock(bfw->watch_fd, bfw->watch_flags); } return rearmType; } @@ -793,7 +793,7 @@ template class EventLoop if (LoopTraits::has_separate_rw_fd_watches) { // TODO this will need flags for such a loop, since it can't // otherwise distinguish which channel watch to remove - loop_mech.removeFdWatch_nolock(bdfw->watch_fd); + loop_mech.removeFdWatch_nolock(bdfw->watch_fd, bdfw->watch_flags); return bdfw->read_removed ? Rearm::REMOVE : Rearm::NOOP; } else { @@ -802,7 +802,7 @@ template class EventLoop } else { // both removed: actually remove - loop_mech.removeFdWatch_nolock(bdfw->watch_fd); + loop_mech.removeFdWatch_nolock(bdfw->watch_fd, 0 /* not used */); return Rearm::REMOVE; } } @@ -846,6 +846,8 @@ template class EventLoop bool is_multi_watch = false; BaseBidiFdWatcher *bbfw = nullptr; + // (Above variables are initialised only to silence compiler warnings). + // Read/manipulate watch_flags (if necessary) *before* we release the lock: if (pqueue->watchType == WatchType::FD) { BaseFdWatcher *bfw = static_cast(pqueue); @@ -868,8 +870,6 @@ template class EventLoop ed.lock.unlock(); - // (Above variables are initialised only to silence compiler warnings). - // Note that we select actions based on the type of the watch, as determined by the watchType // member. In some ways this screams out for polmorphism; a virtual function could be overridden // by each of the watcher types. I've instead used switch/case because I think it will perform @@ -933,9 +933,7 @@ template class EventLoop default: ; } - if (pqueue->deleteme) rearmType = Rearm::REMOVE; // makes the watchRemoved() callback get called. - - if (rearmType == Rearm::REMOVE) { + if (pqueue->deleteme || rearmType == Rearm::REMOVE) { ed.lock.unlock(); (is_multi_watch ? bbfw : pqueue)->watchRemoved(); ed.lock.lock(); -- 2.25.1