From 3c4f4f003d9fdbf759e42ced4fece8dd6a506298 Mon Sep 17 00:00:00 2001
From: Ben Longbons <b.r.longbons@gmail.com>
Date: Fri, 14 Mar 2014 19:25:35 -0700
Subject: Fix session death and shutdown when bored

---
 src/common/socket.cpp | 27 ++++++++++++++++++++++++---
 src/common/timer.cpp  |  5 +++++
 src/common/timer.hpp  |  3 +++
 src/common/utils2.hpp |  2 +-
 4 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/src/common/socket.cpp b/src/common/socket.cpp
index b5f6379..73e32a4 100644
--- a/src/common/socket.cpp
+++ b/src/common/socket.cpp
@@ -13,7 +13,8 @@
 #include <ctime>
 
 #include "../io/cxxstdio.hpp"
-//#include "mmo.hpp"
+#include "core.hpp"
+#include "timer.hpp"
 #include "utils.hpp"
 
 #include "../poison.hpp"
@@ -377,12 +378,26 @@ void WFIFOSET(Session *s, size_t len)
 
 void do_sendrecv(interval_t next_ms)
 {
+    bool any = false;
     io::FD_Set rfd = readfds, wfd;
     for (io::FD i : iter_fds())
     {
         Session *s = get_session(i);
-        if (s && s->wdata_size)
-            wfd.set(i);
+        if (s)
+        {
+            any = true;
+            if (s->wdata_size)
+                wfd.set(i);
+        }
+    }
+    if (!any)
+    {
+        if (!has_timers())
+        {
+            PRINTF("Shutting down - nothing to do\n");
+            runflag = false;
+        }
+        return;
     }
     struct timeval timeout;
     {
@@ -433,6 +448,12 @@ void do_parsepacket(void)
         {
             s->func_parse(s);
             /// some func_parse may call delete_session
+            s = get_session(i);
+            if (s && s->eof)
+            {
+                delete_session(s);
+                s = nullptr;
+            }
             if (!s)
                 continue;
         }
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index ee62df2..b5a2a5e 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -194,3 +194,8 @@ tick_t file_modified(ZString name)
         return tick_t();
     return tick_t(std::chrono::seconds(buf.st_mtime));
 }
+
+bool has_timers()
+{
+    return !timer_heap.empty();
+}
diff --git a/src/common/timer.hpp b/src/common/timer.hpp
index a54cb36..7e187a3 100644
--- a/src/common/timer.hpp
+++ b/src/common/timer.hpp
@@ -24,4 +24,7 @@ interval_t do_timer(tick_t tick);
 /// Stat a file, and return its modification time, truncated to seconds.
 tick_t file_modified(ZString name);
 
+/// Check if there are any events at all scheduled.
+bool has_timers();
+
 #endif // TIMER_HPP
diff --git a/src/common/utils2.hpp b/src/common/utils2.hpp
index ac55a5a..9af39e5 100644
--- a/src/common/utils2.hpp
+++ b/src/common/utils2.hpp
@@ -199,7 +199,7 @@ struct is_array_of_unknown_bound
 template<class T, class D=std::default_delete<T>, class... A>
 typename std::enable_if<!is_array_of_unknown_bound<T>::value, std::unique_ptr<T, D>>::type make_unique(A&&... a)
 {
-    return std::unique_ptr<T, D>(new T(a...));
+    return std::unique_ptr<T, D>(new T(std::forward<A>(a)...));
 }
 
 template<class T, class D=std::default_delete<T>>
-- 
cgit v1.2.3-70-g09d2