Incorporate latest bugfixes from dasynq
authorDavin McCall <davmac@davmac.org>
Sat, 11 Jun 2016 18:24:02 +0000 (19:24 +0100)
committerDavin McCall <davmac@davmac.org>
Sat, 11 Jun 2016 18:24:02 +0000 (19:24 +0100)
src/dasync/dasync-childproc.h [new file with mode: 0644]
src/dasync/dasync-epoll.h
src/dasync/dasync.h

diff --git a/src/dasync/dasync-childproc.h b/src/dasync/dasync-childproc.h
new file mode 100644 (file)
index 0000000..f92d4c6
--- /dev/null
@@ -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<pid_t, void *>;
+    std::unordered_map<pid_t, void *> base_map;
+    std::vector<pair> 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<bool, void *>;
+
+    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 Base> 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 <typename T> void init(T *loop_mech)
+    {
+        loop_mech->addSignalWatch(SIGCHLD, nullptr);
+    }
+};
+
+
+} // end namespace
index 8dae802c74ef1093420eb0ba8a8556dd0dd0a5d0..26225a27b5210798ae1732acbc81f2978291ac28 100644 (file)
@@ -138,6 +138,7 @@ template <class Base> class EpollLoop : public Base
             throw std::system_error(errno, std::system_category());
         }
         sigemptyset(&sigmask);
+        Base::init(this);
     }
     
     ~EpollLoop()
@@ -321,120 +322,4 @@ template <class Base> 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<pid_t, void *>;
-    std::unordered_map<pid_t, void *> base_map;
-    std::vector<pair> 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<bool, void *>;
-
-    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 Base> 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
index c4d16d324da8c714a6d068ebd2f8e464be765c99..62a70d876bc6cc67d1c95a2cef19ba5941d3db25 100644 (file)
 
 #if defined(HAVE_KQUEUE)
 #include "dasync-kqueue.h"
+#include "dasync-childproc.h"
 namespace dasync {
     template <typename T> using Loop = KqueueLoop<T>;
     using LoopTraits = KqueueTraits;
 }
 #elif defined(HAVE_EPOLL)
 #include "dasync-epoll.h"
+#include "dasync-childproc.h"
 namespace dasync {
     template <typename T> using Loop = EpollLoop<T>;
     using LoopTraits = EpollTraits;
@@ -516,13 +518,11 @@ template <typename T_Mutex> 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 <typename T_Mutex> 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 <typename T_Mutex> class EventLoop
             else {
                 q->active = true;
                 active = true;
+                prev = q;
             }
         }