summaryrefslogtreecommitdiff
path: root/src/service.c
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 /src/service.c
parentb1db68fa60d4257d5cc84b512719dd99e856d82f (diff)
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.
Diffstat (limited to 'src/service.c')
-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);