chiark / gitweb /
service: handle forking services that move to a new PID
authorMichal Schmidt <mschmidt@redhat.com>
Tue, 20 Sep 2011 19:43:30 +0000 (21:43 +0200)
committerMichal Schmidt <mschmidt@redhat.com>
Tue, 20 Sep 2011 22:57:41 +0000 (00:57 +0200)
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.

src/service.c

index 6f1a85e..8f827aa 100644 (file)
@@ -1269,9 +1269,6 @@ static int service_load_pid_file(Service *s) {
 
         assert(s);
 
-        if (s->main_pid_known)
-                return 0;
-
         if (!s->pid_file)
                 return 0;
 
@@ -1290,6 +1287,16 @@ static int service_load_pid_file(Service *s) {
                 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;
 
@@ -2575,6 +2582,11 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                 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, &s->exec_context, pid, code, status);