Fix #227: delayed service_kill() may stall shutdown/reboot

This turns out to be the root-cause of #227.  Finit is waiting forever
for proceeses to stop at shutdown/reboot, while a subreaper has already
collected the PID, or Finit for some reason did not collect the PID.

When the process timeout calls service_kill() we now check if the kernel
actually knows of this process or not.  If it's already been collected,
we can notify Finit of this by calling service_monitor() to clean up the
'svc' and in turn call sm_step() to finalize the state transition.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2023-06-27 12:18:09 +02:00
1 parent 0c9b7a67e0
commit 6f0d448765
1 file changed
+13 -4
+13 -4
View File
@@ -850,17 +850,26 @@ fail:
*/ */
static void service_kill(svc_t *svc) static void service_kill(svc_t *svc)
{ {
char *nm, *id = svc_ident(svc, NULL, 0);
service_timeout_cancel(svc); service_timeout_cancel(svc);
if (svc->pid <= 1) { if (svc->pid <= 1) {
/* Avoid killing ourselves or all processes ... */ /* Avoid killing ourselves or all processes ... */
dbg("%s: Aborting SIGKILL, already terminated.", svc_ident(svc, NULL, 0)); dbg("%s: Aborting SIGKILL, already terminated.", id);
return; return;
} }
dbg("%s: Sending SIGKILL to process group %d", pid_get_name(svc->pid, NULL, 0), svc->pid); nm = pid_get_name(svc->pid, NULL, 0);
logit(LOG_CONSOLE | LOG_NOTICE, "Stopping %s[%d], sending SIGKILL ...", if (!nm) {
svc_ident(svc, NULL, 0), svc->pid); /* PID possibly monitored by someone else? */
dbg("%s: Aborting SIGKILL, PID[%d] no longer exists.", id, svc->pid);
service_monitor(svc->pid, 0);
return;
}
dbg("%s: Sending SIGKILL to process group %d", nm, svc->pid);
logit(LOG_CONSOLE | LOG_NOTICE, "Stopping %s[%d], sending SIGKILL ...", id, svc->pid);
if (runlevel != 1) if (runlevel != 1)
print_desc("Killing ", svc->desc); print_desc("Killing ", svc->desc);