From 95c34ef8180a4900332f8df36d9564453de09faf Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Sat, 11 Jun 2016 19:24:02 +0100 Subject: [PATCH] Incorporate latest bugfixes from dasynq --- src/dasync/dasync-childproc.h | 125 ++++++++++++++++++++++++++++++++++ src/dasync/dasync-epoll.h | 117 +------------------------------ src/dasync/dasync.h | 6 +- 3 files changed, 130 insertions(+), 118 deletions(-) create mode 100644 src/dasync/dasync-childproc.h diff --git a/src/dasync/dasync-childproc.h b/src/dasync/dasync-childproc.h new file mode 100644 index 0000000..f92d4c6 --- /dev/null +++ b/src/dasync/dasync-childproc.h @@ -0,0 +1,125 @@ +namespace dasync { + +// Map of pid_t to void *, with possibility of reserving entries so that mappings can +// be later added with no danger of allocator exhaustion (bad_alloc). +class pid_map +{ + using pair = std::pair; + std::unordered_map base_map; + std::vector backup_vector; + + // Number of entries in backup_vector that are actually in use (as opposed + // to simply reserved): + int backup_size = 0; + + public: + using entry = std::pair; + + entry get(pid_t key) noexcept + { + auto it = base_map.find(key); + if (it == base_map.end()) { + // Not in map; look in vector + for (int i = 0; i < backup_size; i++) { + if (backup_vector[i].first == key) { + return entry(true, backup_vector[i].second); + } + } + + return entry(false, nullptr); + } + + return entry(true, it->second); + } + + entry erase(pid_t key) noexcept + { + auto iter = base_map.find(key); + if (iter != base_map.end()) { + entry r(true, iter->second); + base_map.erase(iter); + return r; + } + for (int i = 0; i < backup_size; i++) { + if (backup_vector[i].first == key) { + entry r(true, backup_vector[i].second); + backup_vector.erase(backup_vector.begin() + i); + return r; + } + } + return entry(false, nullptr); + } + + // Throws bad_alloc on reservation failure + void reserve() + { + backup_vector.resize(backup_vector.size() + 1); + } + + void add(pid_t key, void *val) // throws std::bad_alloc + { + base_map[key] = val; + } + + void add_from_reserve(pid_t key, void *val) noexcept + { + try { + base_map[key] = val; + backup_vector.resize(backup_vector.size() - 1); + } + catch (std::bad_alloc &) { + // We couldn't add into the map, use the reserve: + backup_vector[backup_size++] = pair(key, val); + } + } +}; + +template class ChildProcEvents : public Base +{ + private: + pid_map child_waiters; + + using SigInfo = typename Base::SigInfo; + + protected: + void receiveSignal(SigInfo &siginfo, void *userdata) + { + if (siginfo.get_signo() == SIGCHLD) { + int status; + pid_t child; + while ((child = waitpid(-1, &status, WNOHANG)) > 0) { + pid_map::entry ent = child_waiters.erase(child); + if (ent.first) { + Base::receiveChildStat(child, status, ent.second); + } + } + } + else { + Base::receiveSignal(siginfo, userdata); + } + } + + public: + void reserveChildWatch() + { + child_waiters.reserve(); + } + + void addChildWatch(pid_t child, void *val) + { + child_waiters.add(child, val); + } + + void addReservedChildWatch(pid_t child, void *val) noexcept + { + child_waiters.add_from_reserve(child, val); + } + + template void init(T *loop_mech) + { + loop_mech->addSignalWatch(SIGCHLD, nullptr); + } +}; + + +} // end namespace diff --git a/src/dasync/dasync-epoll.h b/src/dasync/dasync-epoll.h index 8dae802..26225a2 100644 --- a/src/dasync/dasync-epoll.h +++ b/src/dasync/dasync-epoll.h @@ -138,6 +138,7 @@ template class EpollLoop : public Base throw std::system_error(errno, std::system_category()); } sigemptyset(&sigmask); + Base::init(this); } ~EpollLoop() @@ -321,120 +322,4 @@ template class EpollLoop : public Base } }; -// Map of pid_t to void *, with possibility of reserving entries so that mappings can -// be later added with no danger of allocator exhaustion (bad_alloc). -class pid_map -{ - using pair = std::pair; - std::unordered_map base_map; - std::vector backup_vector; - - // Number of entries in backup_vector that are actually in use (as opposed - // to simply reserved): - int backup_size = 0; - - public: - using entry = std::pair; - - entry get(pid_t key) noexcept - { - auto it = base_map.find(key); - if (it == base_map.end()) { - // Not in map; look in vector - for (int i = 0; i < backup_size; i++) { - if (backup_vector[i].first == key) { - return entry(true, backup_vector[i].second); - } - } - - return entry(false, nullptr); - } - - return entry(true, it->second); - } - - entry erase(pid_t key) noexcept - { - auto iter = base_map.find(key); - if (iter != base_map.end()) { - entry r(true, iter->second); - base_map.erase(iter); - return r; - } - for (int i = 0; i < backup_size; i++) { - if (backup_vector[i].first == key) { - entry r(true, backup_vector[i].second); - backup_vector.erase(backup_vector.begin() + i); - return r; - } - } - return entry(false, nullptr); - } - - // Throws bad_alloc on reservation failure - void reserve() - { - backup_vector.resize(backup_vector.size() + 1); - } - - void add(pid_t key, void *val) // throws std::bad_alloc - { - base_map[key] = val; - } - - void add_from_reserve(pid_t key, void *val) noexcept - { - try { - base_map[key] = val; - backup_vector.resize(backup_vector.size() - 1); - } - catch (std::bad_alloc &) { - // We couldn't add into the map, use the reserve: - backup_vector[backup_size++] = pair(key, val); - } - } -}; - -template class ChildProcEvents : public Base -{ - private: - pid_map child_waiters; - - using SigInfo = typename Base::SigInfo; - - protected: - void receiveSignal(SigInfo &siginfo, void *userdata) - { - if (siginfo.get_signo() == SIGCHLD) { - int status; - pid_t child; - while ((child = waitpid(-1, &status, WNOHANG)) > 0) { - pid_map::entry ent = child_waiters.erase(child); - if (ent.first) { - Base::receiveChildStat(child, status, ent.second); - } - } - } - else { - Base::receiveSignal(siginfo, userdata); - } - } - - public: - void reserveChildWatch() - { - child_waiters.reserve(); - } - - void addChildWatch(pid_t child, void *val) - { - child_waiters.add(child, val); - } - - void addReservedChildWatch(pid_t child, void *val) noexcept - { - child_waiters.add_from_reserve(child, val); - } -}; - } // end namespace diff --git a/src/dasync/dasync.h b/src/dasync/dasync.h index c4d16d3..62a70d8 100644 --- a/src/dasync/dasync.h +++ b/src/dasync/dasync.h @@ -11,12 +11,14 @@ #if defined(HAVE_KQUEUE) #include "dasync-kqueue.h" +#include "dasync-childproc.h" namespace dasync { template using Loop = KqueueLoop; using LoopTraits = KqueueTraits; } #elif defined(HAVE_EPOLL) #include "dasync-epoll.h" +#include "dasync-childproc.h" namespace dasync { template using Loop = EpollLoop; using LoopTraits = EpollTraits; @@ -516,13 +518,11 @@ template class EventLoop void reserveChildWatch(BaseChildWatcher *callBack) { - loop_mech.addSignalWatch(SIGCHLD, nullptr); // TODO remove this kludge loop_mech.reserveChildWatch(); } void registerChild(BaseChildWatcher *callBack, pid_t child) { - loop_mech.addSignalWatch(SIGCHLD, nullptr); // TODO remove this kludge loop_mech.addChildWatch(child, callBack); } @@ -672,6 +672,7 @@ template class EventLoop BaseWatcher * prev = nullptr; for (BaseWatcher * q = pqueue; q != nullptr; q = q->next) { if (q->deleteme) { + // TODO should this really be called with lock held? q->watchRemoved(); if (prev) { prev->next = q->next; @@ -683,6 +684,7 @@ template class EventLoop else { q->active = true; active = true; + prev = q; } } -- 2.25.1