Add the "termsignal" setting to process services. This allows an
authorDavin McCall <davmac@davmac.org>
Thu, 19 Nov 2015 11:02:18 +0000 (11:02 +0000)
committerDavin McCall <davmac@davmac.org>
Thu, 19 Nov 2015 11:02:18 +0000 (11:02 +0000)
additional signal (alongside SIGTERM) to be sent to the process to
terminate it.

load_service.cc
service.cc
service.h

index fcfcab85217619c07c4277125d62cad9a66236be..46887cd4a8726002be1254916ee3a455d0ce8b2f 100644 (file)
@@ -161,6 +161,15 @@ static string read_setting_value(string_iterator & i, string_iterator end,
     return rval;
 }
 
+static int signalNameToNumber(std::string &signame)
+{
+    if (signame == "HUP") return SIGHUP;
+    if (signame == "INT") return SIGINT;
+    if (signame == "QUIT") return SIGQUIT;
+    if (signame == "USR1") return SIGUSR1;
+    if (signame == "USR2") return SIGUSR2;
+    return -1;
+}
 
 // Find a service record, or load it from file. If the service has
 // dependencies, load those also.
@@ -201,6 +210,7 @@ ServiceRecord * ServiceSet::loadServiceRecord(const char * name)
     std::list<ServiceRecord *> depends_soft;
     string logfile;
     OnstartFlags onstart_flags;
+    int term_signal = -1;  // additional termination signal
     
     string line;
     bool auto_restart = false;
@@ -288,6 +298,16 @@ ServiceRecord * ServiceSet::loadServiceRecord(const char * name)
                     }
                 }
             }
+            else if (setting == "termsignal") {
+                string signame = read_setting_value(i, end, nullptr);
+                int signo = signalNameToNumber(signame);
+                if (signo == -1) {
+                    throw new ServiceDescriptionExc(name, "Unknown/unsupported termination signal: " + signame);
+                }
+                else {
+                    term_signal = signo;
+                }
+            }
             else {
                 throw ServiceDescriptionExc(name, "Unknown setting: " + setting);
             }
@@ -307,6 +327,7 @@ ServiceRecord * ServiceSet::loadServiceRecord(const char * name)
             rval->setLogfile(logfile);
             rval->setAutoRestart(auto_restart);
             rval->setOnstartFlags(onstart_flags);
+            rval->setExtraTerminationSignal(term_signal);
             *iter = rval;
             break;
         }
index fa52aa7187ed20eaf14dbf72c11f375c25030e4e..bc989254e90b1efca30cafe9506fc19e8df643e8 100644 (file)
@@ -514,6 +514,9 @@ void ServiceRecord::allDepsStopped()
         if (pid != -1) {
           // The process is still kicking on - must actually kill it.
           kill(pid, SIGTERM);
+          if (term_signal != -1) {
+              kill(pid, term_signal);
+          }
           // Now we wait; the rest is done in process_child_callback
         }
         else {
index 4eab4b1718ed36fababba38023d474b0e0e87c19..b391cc8360ac16bf0b8f9b5ef42fcd7426be4751 100644 (file)
--- a/service.h
+++ b/service.h
@@ -1,6 +1,7 @@
 #include <string>
 #include <list>
 #include <vector>
+#include <csignal>
 #include "ev.h"
 
 /*
@@ -187,6 +188,8 @@ class ServiceRecord
                      // case if for example the process dies; the service,
                      // and all its dependencies, MUST be stopped.
 
+    int term_signal = -1;  // signal to use for process termination
+
     // Implementation details
     
     pid_t pid;  /* PID of the process. If state is STARTING or STOPPING,
@@ -294,6 +297,12 @@ class ServiceRecord
     {
         this->onstart_flags = flags;
     }
+    
+    // Set an additional signal (other than SIGTERM) to be used to terminate the process
+    void setExtraTerminationSignal(int signo)
+    {
+        this->term_signal = signo;
+    }
 
     const char *getServiceName() const { return service_name.c_str(); }
     ServiceState getState() const { return service_state; }