mirror of
https://github.com/troglobit/finit.git
synced 2026-10-05 07:13:44 +07:00
Fix #355: regression stopping a process and its group
In91a9c83a regression was introduced that affects the way Finit stops a supervised process and its process group. Instead of sending SIGTERM to the process, delegating the responsibility to that process to inform any children it may have, Finit as of91a9c83sends SIGTERM to the entire process group. For SIGKILL this is fine, SIGKILL only runs as cleanup and as a last ditch effort if the process doesn't respond to SIGTERM. This regression, introduced in v3.2, directly affects services like avahi-autoipd that have forked off children that it needs to tell to exit cleanly before it returns. With the patch in question these children are never allowed to complete, which in turn causes lingering 169.254 link-local addresses on interfaces. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+13
-6
@@ -173,7 +173,7 @@ static int service_script_del(pid_t pid)
|
||||
if (ptr->pid != pid)
|
||||
continue;
|
||||
|
||||
dbg("Collected service %s script PID %d.", svc_ident(ptr->svc, NULL, 0), pid);
|
||||
dbg("Collected service %s script PID %d, killing process group.", svc_ident(ptr->svc, NULL, 0), pid);
|
||||
service_timeout_cancel(ptr->svc);
|
||||
kill(-ptr->pid, SIGKILL);
|
||||
TAILQ_REMOVE(&svc_assoc_list, ptr, link);
|
||||
@@ -865,7 +865,7 @@ static void service_kill(svc_t *svc)
|
||||
return;
|
||||
}
|
||||
|
||||
dbg("%s: Sending SIGKILL to pid:%d", pid_get_name(svc->pid, NULL, 0), svc->pid);
|
||||
dbg("%s: Sending SIGKILL to process group %d", pid_get_name(svc->pid, NULL, 0), svc->pid);
|
||||
logit(LOG_CONSOLE | LOG_NOTICE, "Stopping %s[%d], sending SIGKILL ...",
|
||||
svc_ident(svc, NULL, 0), svc->pid);
|
||||
if (runlevel != 1)
|
||||
@@ -969,9 +969,14 @@ int service_stop(svc_t *svc)
|
||||
|
||||
if (!svc_is_sysv(svc)) {
|
||||
if (svc->pid > 1) {
|
||||
/* Kill all children in the same proess group, e.g. logit */
|
||||
rc = kill(-svc->pid, svc->sighalt);
|
||||
dbg("kill(-%d, %d) => rc %d, errno %d", svc->pid, svc->sighalt, rc, errno);
|
||||
/*
|
||||
* Send SIGTERM to parent process of process group, not to the
|
||||
* entire group. This gives the process time to properly stop
|
||||
* and/or forward TERM to its children. If it does not respond
|
||||
* in within a reasonable timeout we SIGKILL the entire group.
|
||||
*/
|
||||
rc = kill(svc->pid, svc->sighalt);
|
||||
dbg("kill(%d, %d) => rc %d, errno %d", svc->pid, svc->sighalt, rc, errno);
|
||||
/* PID lost or forking process never really started */
|
||||
if (rc == -1 && (errno == ESRCH || errno == ENOENT)) {
|
||||
service_cleanup(svc);
|
||||
@@ -1837,6 +1842,8 @@ void service_monitor(pid_t lost, int status)
|
||||
dbg("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d",
|
||||
svc->state == SVC_CLEANUP_STATE ? svc->post_script : svc->pre_script,
|
||||
lost, WIFEXITED(status), WIFSIGNALED(status), WEXITSTATUS(status));
|
||||
/* Kill all children in the same proess group, e.g. logit */
|
||||
dbg("Killing lingering children in same process group ...");
|
||||
kill(-svc->pid, SIGKILL);
|
||||
goto done;
|
||||
|
||||
@@ -1858,8 +1865,8 @@ void service_monitor(pid_t lost, int status)
|
||||
logit(LOG_CONSOLE | LOG_NOTICE, "Stopped %s[%d]", svc_ident(svc, NULL, 0), lost);
|
||||
}
|
||||
|
||||
|
||||
/* Terminate any children in the same proess group, e.g. logit */
|
||||
dbg("Killing lingering children in same process group ...");
|
||||
kill(-svc->pid, SIGKILL);
|
||||
|
||||
/* Try removing PID file (in case service does not clean up after itself) */
|
||||
|
||||
Reference in New Issue
Block a user