From 7c2764790c967282852c1237a2278ee901928594 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 13 Jan 2023 08:04:55 +0100 Subject: [PATCH] Issue #343: READY state lost when service is restarted after crash The svc_set_state() function not only handles state transitions, it also makes sure to cancel any outstaing service timeouts. Before the service readiness support was added, service conditions were simply a single bit of information, so clearing its conditions before changing states had no impact. With readiness we have multiple bits of information that are set as conditions. When restarting a crashing service we set a timeout to retry restarting, or ensure the service is now running. This means that the service can signal READY before RUNNING is reasserted, but the RUNNING state can be set also by the service state machine, so we need to ensure we do not re-assert RUNNING if it's already set, and thereby clearing READY. Signed-off-by: Joachim Wiberg --- src/service.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/service.c b/src/service.c index 864f1f58..45ddb8b1 100644 --- a/src/service.c +++ b/src/service.c @@ -2035,16 +2035,18 @@ static void svc_set_state(svc_t *svc, svc_state_t new_state) { svc_state_t *state = (svc_state_t *)&svc->state; - *state = new_state; - /* if PID isn't collected within SVC_TERM_TIMEOUT msec, kill it! */ - if (*state == SVC_STOPPING_STATE) { + if (new_state == SVC_STOPPING_STATE) { dbg("%s is stopping, wait %d sec before sending SIGKILL ...", svc_ident(svc, NULL, 0), svc->killdelay / 1000); service_timeout_cancel(svc); service_timeout_after(svc, svc->killdelay, service_kill); } + if (svc->state == new_state) + return; + *state = new_state; + if (svc_is_runtask(svc)) { char success[MAX_COND_LEN], failure[MAX_COND_LEN];