Skip to content

Commit

Permalink
Fix #227: set svc state late when stopping services, nay be dead
Browse files Browse the repository at this point in the history
A service may have unexpectedly died, and we never got the signal, so
when stopping services we must set the new state after we've tried to
stop the service.  Otherwise the svc_set_state() function starts a
background timer for the SIGKILL job, which may block a reboot.

The kill() syscall tells us if the service was there or not, if not we
must clean up and go to HALTED state.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
  • Loading branch information
troglobit committed Mar 22, 2022
1 parent 996ab8c commit 7dc7f9a
Showing 1 changed file with 10 additions and 6 deletions.
16 changes: 10 additions & 6 deletions src/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -746,8 +746,6 @@ static int service_stop(svc_t *svc)
*/
svc_started(svc);

svc_set_state(svc, SVC_STOPPING_STATE);

if (!svc->desc[0])
do_progress = 0;

Expand All @@ -758,12 +756,17 @@ static int service_stop(svc_t *svc)
if (svc->pid > 1) {
/* Kill all children in the same proess group, e.g. logit */
rc = kill(-svc->pid, svc->sighalt);
_d("kill(-%d, %d) => rc %d", svc->pid, svc->sighalt, rc);
_d("kill(-%d, %d) => rc %d, errno %d", svc->pid, svc->sighalt, rc, errno);
/* PID lost or forking process never really started */
if (rc == -1 && ESRCH == errno)
service_cleanup(svc);
} else
if (rc == -1 && errno == ESRCH) {
service_cleanup(svc);
svc_set_state(svc, SVC_HALTED_STATE);
} else
svc_set_state(svc, SVC_STOPPING_STATE);
} else {
service_cleanup(svc);
svc_set_state(svc, SVC_HALTED_STATE);
}
} else {
char *args[] = { svc->cmd, "stop", NULL };
pid_t pid;
Expand All @@ -781,6 +784,7 @@ static int service_stop(svc_t *svc)
rc = 1;
break;
default:
svc_set_state(svc, SVC_STOPPING_STATE);
rc = WEXITSTATUS(complete(svc->cmd, pid));
break;
}
Expand Down

0 comments on commit 7dc7f9a

Please sign in to comment.