Blob Blame History Raw
From db01f8b3f870611a013b913636bb7fefaab34018 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Tue, 20 Sep 2011 21:43:30 +0200
Subject: [PATCH] service: handle forking services that move to a new PID

When some forking daemons receive a SIGHUP, they re-execute themselves
and consequently change to a new main PID. As long as they update the
PID file in the right order (before exiting the old PID), we can detect
that and avoid killing them.
---

[ unfuzzed with quilt -- michich ]

 src/service.c |   18 +++++++++++++++---
 1 files changed, 15 insertions(+), 3 deletions(-)

Index: systemd-26/src/service.c
===================================================================
--- systemd-26.orig/src/service.c
+++ systemd-26/src/service.c
@@ -1264,9 +1264,6 @@ static int service_load_pid_file(Service
 
         assert(s);
 
-        if (s->main_pid_known)
-                return 0;
-
         if (!s->pid_file)
                 return 0;
 
@@ -1285,6 +1282,16 @@ static int service_load_pid_file(Service
                 return -ESRCH;
         }
 
+        if (s->main_pid_known) {
+                if (pid == s->main_pid)
+                        return 0;
+
+                log_debug("Main PID changing: %lu -> %lu",
+                          (unsigned long) s->main_pid, (unsigned long) pid);
+                service_unwatch_main_pid(s);
+                s->main_pid_known = false;
+        }
+
         if ((r = service_set_main_pid(s, pid)) < 0)
                 return r;
 
@@ -2569,6 +2576,11 @@ static void service_sigchld_event(Unit *
                 success = is_clean_exit(code, status);
 
         if (s->main_pid == pid) {
+                /* Forking services may occasionally move to a new PID.
+                 * As long as they update the PID file before exiting the old
+                 * PID, they're fine. */
+                if (s->pid_file && service_load_pid_file(s) == 0)
+                        return;
 
                 s->main_pid = 0;
                 exec_status_exit(&s->main_exec_status, pid, code, status, s->exec_context.utmp_id);