Use getpgid to determine process group of service process.
authorDavin McCall <davmac@davmac.org>
Mon, 3 Jul 2017 00:10:28 +0000 (01:10 +0100)
committerDavin McCall <davmac@davmac.org>
Mon, 3 Jul 2017 00:10:28 +0000 (01:10 +0100)
Using pid (i.e. 'kill(-pid, signo)') doesn't work if the process has
double-forked but not set a new process group for the child, and
anyway it's not clear if POSIX actually guarantees that process group
IDs will match process IDs.

src/service.cc
src/service.h

index 6c249dfb956097bd47370556b94b53c5ebef83fb..8fa93ecc72bda96101303e40c50807d137a6ee50 100644 (file)
@@ -1222,6 +1222,17 @@ void service_record::all_deps_stopped() noexcept
     stopped();
 }
 
+void base_process_service::kill_pg(int signo) noexcept
+{
+    pid_t pgid = getpgid(pid);
+    if (pgid == -1) {
+        // only should happen if pid is invalid, which should never happen...
+        log(LogLevel::ERROR, service_name, ": can't signal process: ", strerror(errno));
+        return;
+    }
+    kill(-pgid, signo);
+}
+
 void base_process_service::all_deps_stopped() noexcept
 {
     waiting_for_deps = false;
@@ -1230,10 +1241,10 @@ void base_process_service::all_deps_stopped() noexcept
         // group (-pid) rather than just the process as there's less risk then of creating
         // an orphaned process group:
         if (! onstart_flags.no_sigterm) {
-            kill(-pid, SIGTERM);
+            kill_pg(SIGTERM);
         }
         if (term_signal != -1) {
-            kill(-pid, term_signal);
+            kill_pg(term_signal);
         }
 
         // In most cases, the rest is done in handle_exit_status.
@@ -1419,8 +1430,8 @@ void base_process_service::interrupt_start() noexcept
 void base_process_service::kill_with_fire() noexcept
 {
     if (pid != -1) {
-        log(LogLevel::WARN, "Service ", service_name, " exceeded allowed stop time; killing.");
-        kill(-pid, SIGKILL);
+        log(LogLevel::WARN, "Service ", service_name, "with pid ", pid, " exceeded allowed stop time; killing.");
+        kill_pg(SIGKILL);
     }
 }
 
index 2ecbf7f839291358c659253ebf34d71fcc9f9298..8e235933d16323d882acb57620dc6901e748374d 100644 (file)
@@ -656,6 +656,9 @@ class base_process_service : public service_record
     // Kill with SIGKILL
     void kill_with_fire() noexcept;
 
+    // Signal the process group of the service process
+    void kill_pg(int signo) noexcept;
+
     public:
     base_process_service(service_set *sset, string name, service_type record_type_p, string &&command,
             std::list<std::pair<unsigned,unsigned>> &command_offsets,