From 42fa09a6fa1c70ee274eec5c2c796377f3e71954 Mon Sep 17 00:00:00 2001
From: Adrien Beraud <adrien.beraud@savoirfairelinux.com>
Date: Thu, 29 Jun 2017 10:20:31 +0200
Subject: [PATCH] dhtnode: graceful signal handling in service and daemon modes

---
 tools/dhtnode.cpp    |  3 +--
 tools/tools_common.h | 26 +++++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp
index 8ed1769b..8aaf75f3 100644
--- a/tools/dhtnode.cpp
+++ b/tools/dhtnode.cpp
@@ -386,8 +386,7 @@ main(int argc, char **argv)
         }
 
         if (params.daemonize or params.service) {
-            while (true)
-                std::this_thread::sleep_for(std::chrono::seconds(30));
+            while (runner.wait());
         } else {
             cmd_loop(dht, params);
         }
diff --git a/tools/tools_common.h b/tools/tools_common.h
index d8cc540b..933cc7e2 100644
--- a/tools/tools_common.h
+++ b/tools/tools_common.h
@@ -18,6 +18,7 @@
  */
 
 // Common utility methods used by C++ OpenDHT tools.
+#pragma once
 
 #include <opendht.h>
 #ifndef WIN32_NATIVE
@@ -37,6 +38,8 @@
 #include <string>
 #include <vector>
 #include <chrono>
+#include <mutex>
+#include <condition_variable>
 #include <iostream>
 #include <sstream>
 #include <fstream>
@@ -204,13 +207,33 @@ readLine(const char* prefix = PROMPT)
     return line_read ? std::string(line_read) : std::string("\0", 1);
 }
 
+struct ServiceRunner {
+    bool wait() {
+        std::unique_lock<std::mutex> lock(m);
+        cv.wait(lock, [&]{return terminate;});
+        return !terminate;
+    }
+    void kill() {
+        std::lock_guard<std::mutex> lock(m);
+        terminate = true;
+        cv.notify_all();
+    }
+private:
+    std::condition_variable cv;
+    std::mutex m;
+    bool terminate = false;
+};
+
+ServiceRunner runner;
+
 void signal_handler(int sig)
 {
     switch(sig) {
     case SIGHUP:
         break;
+    case SIGINT:
     case SIGTERM:
-        exit(EXIT_SUCCESS);
+        runner.kill();
         break;
     }
 }
@@ -223,6 +246,7 @@ void setupSignals()
     signal(SIGTTOU,SIG_IGN);
     signal(SIGTTIN,SIG_IGN);
     signal(SIGHUP,signal_handler); /* catch hangup signal */
+    signal(SIGINT,signal_handler); /* catch interrupt signal */
     signal(SIGTERM,signal_handler); /* catch kill signal */
 #endif
 }
-- 
GitLab