diff options
author | Michal Schmidt <mschmidt@redhat.com> | 2011-09-20 21:43:30 +0200 |
---|---|---|
committer | Michal Schmidt <mschmidt@redhat.com> | 2011-09-21 00:57:41 +0200 |
commit | db01f8b3f870611a013b913636bb7fefaab34018 (patch) | |
tree | 9efc3b2a929ab66e84a0c1fa707334ae28fdab7a | |
parent | b1db68fa60d4257d5cc84b512719dd99e856d82f (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.
-rw-r--r-- | src/service.c | 18 |
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); |