summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Schmidt <mschmidt@redhat.com>2011-09-20 21:43:30 +0200
committerMichal Schmidt <mschmidt@redhat.com>2011-09-21 00:57:41 +0200
commitdb01f8b3f870611a013b913636bb7fefaab34018 (patch)
tree9efc3b2a929ab66e84a0c1fa707334ae28fdab7a
parentb1db68fa60d4257d5cc84b512719dd99e856d82f (diff)
downloadsystemd-db01f8b3f870611a013b913636bb7fefaab34018.tar.gz
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.
-rw-r--r--src/service.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/service.c b/src/service.c
index 6f1a85e943..8f827aa520 100644
--- a/src/service.c
+++ b/src/service.c
@@ -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);