diff --git a/src/service.c b/src/service.c index 59c47c30..ecd5f6b1 100644 --- a/src/service.c +++ b/src/service.c @@ -1599,6 +1599,15 @@ int service_restart_now(svc_t *svc) if (!svc) return 1; + if (svc_is_runtask(svc) && svc_is_remain(svc) && + svc->state == SVC_DONE_STATE) { + service_timeout_cancel(svc); + svc_restarting(svc); + service_step(svc); + + return 0; + } + if (!svc_is_running(svc)) return service_start_now(svc); @@ -3378,8 +3387,8 @@ int service_step(svc_t *svc) svc_set_state(svc, SVC_CLEANUP_STATE); service_cleanup_script(svc); } else { - /* Unblock remain tasks after post script so they can restart */ - if (svc_is_remain(svc)) + /* Restart remain tasks after runlevel/reload/restart teardown. */ + if (svc_is_remain(svc) && svc_is_restart(svc)) svc_unblock(svc); svc_set_state(svc, SVC_HALTED_STATE); } @@ -3398,13 +3407,17 @@ int service_step(svc_t *svc) break; case SVC_DONE_STATE: - /* Remain tasks: always run post script when stopped, even if config changed */ - if (svc_is_runtask(svc) && svc_is_remain(svc) && svc_is_stopped(svc)) { + /* Remain tasks run post script before stopping or restarting. */ + if (svc_is_runtask(svc) && svc_is_remain(svc) && + (svc_is_stopped(svc) || svc_is_restart(svc))) { if (svc_has_post(svc)) { svc_set_state(svc, SVC_TEARDOWN_STATE); service_post_script(svc); - } else + } else { + if (svc_is_restart(svc)) + svc_unblock(svc); svc_set_state(svc, SVC_HALTED_STATE); + } } else if (svc_is_changed(svc)) svc_set_state(svc, SVC_HALTED_STATE); else if (svc_is_runtask(svc) && svc_is_manual(svc) && enabled) @@ -3727,7 +3740,7 @@ void service_runtask_clean(void) /* Config changed or leaving runlevel: stop, run post, restart */ svc->once = 0; - svc_stop(svc); + svc_restarting(svc); service_step(svc); continue; } diff --git a/test/Makefile.am b/test/Makefile.am index b943e1ef..b60971aa 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -60,6 +60,7 @@ EXTRA_DIST += pre-fail.sh EXTRA_DIST += process-depends.sh EXTRA_DIST += rclocal.sh EXTRA_DIST += ready-serv.sh +EXTRA_DIST += remain-task-control.sh EXTRA_DIST += restart-self.sh EXTRA_DIST += runlevel.sh EXTRA_DIST += run-restart-forever.sh @@ -129,6 +130,7 @@ TESTS += pre-fail.sh TESTS += process-depends.sh TESTS += rclocal.sh TESTS += ready-serv.sh +TESTS += remain-task-control.sh TESTS += restart-self.sh TESTS += runlevel.sh TESTS += sysvparts.sh diff --git a/test/remain-task-control.sh b/test/remain-task-control.sh new file mode 100755 index 00000000..a5c26eec --- /dev/null +++ b/test/remain-task-control.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +set -eu + +TEST_DIR=$(dirname "$0") +TEST_CONF=/etc/finit.d/remain-task.conf +STATE=/run/remain-task.state + +test_teardown() +{ + run "rm -f $TEST_CONF $STATE" +} + +assert_runs() +{ + assert "Remain task has run $1 time(s)" \ + "$(texec initctl -j status remain-task | jq -M .restarts)" -eq "$1" +} + +# shellcheck source=/dev/null +. "$TEST_DIR/lib/setup.sh" + +say 'Add remain task' +run "cat > $TEST_CONF" <