Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
}
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
76 changes: 76 additions & 0 deletions test/remain-task-control.sh
Original file line number Diff line number Diff line change
@@ -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" <<EOF
task remain-task {
description = "Remain task control"
runlevel = "2345"
remain-after-exit = true
command = "/bin/touch $STATE"
exec-stop-post = "/bin/rm -f $STATE"
}
EOF
run "initctl reload"

retry 'assert_status remain-task done'
assert_file_exists "$STATE"
assert_runs 1

say 'Stop remain task'
run "initctl stop remain-task"
retry 'assert_status remain-task stopped'
assert "Post script removed state" \
"$(texec sh -c "[ ! -e '$STATE' ] && echo yes")" = yes
assert_runs 1

say 'Start remain task'
run "initctl start remain-task"
retry 'assert_status remain-task done'
assert_file_exists "$STATE"
assert_runs 2

say 'Restart remain task'
run "initctl restart remain-task"
retry 'assert_runs 3'
retry 'assert_status remain-task done'
assert_file_exists "$STATE"

say 'Reload changed remain task'
run "sed -i 's/Remain task control/Updated remain task control/' $TEST_CONF"
run "initctl reload"
retry 'assert_runs 4'
retry 'assert_status remain-task done'
assert_file_exists "$STATE"

say 'Leave remain task runlevel'
run "initctl runlevel 1"
retry 'assert_status remain-task halted'
assert "Post script removed state" \
"$(texec sh -c "[ ! -e '$STATE' ] && echo yes")" = yes
assert_runs 4

say 'Re-enter remain task runlevel'
run "initctl runlevel 2"
retry 'assert_runs 5'
retry 'assert_status remain-task done'
assert_file_exists "$STATE"