diff --git a/src/core/service.c b/src/core/service.c index fb97bbeaae..d5f79d274e 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3474,6 +3474,15 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { case SERVICE_START_POST: case SERVICE_RELOAD: + /* If neither main nor control processes are running then + * the current state can never exit cleanly, hence immediately + * terminate the service. */ + if (control_pid_good(s) <= 0) + service_enter_stop(s, f); + + /* Otherwise need to wait untill the operation is done. */ + break; + case SERVICE_STOP: /* Need to wait until the operation is * done */ diff --git a/test/TEST-59-RELOADING-RESTART/Makefile b/test/TEST-59-RELOADING-RESTART/Makefile new file mode 120000 index 0000000000..e9f93b1104 --- /dev/null +++ b/test/TEST-59-RELOADING-RESTART/Makefile @@ -0,0 +1 @@ +../TEST-01-BASIC/Makefile \ No newline at end of file diff --git a/test/TEST-59-RELOADING-RESTART/test.sh b/test/TEST-59-RELOADING-RESTART/test.sh new file mode 100755 index 0000000000..ad990963b8 --- /dev/null +++ b/test/TEST-59-RELOADING-RESTART/test.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e +TEST_DESCRIPTION="Test auto restart of exited services which are stuck in reloading state" + +TEST_NO_QEMU=1 + +. $TEST_BASE_DIR/test-functions + +do_test "$@" 59 diff --git a/test/units/testsuite-59.service b/test/units/testsuite-59.service new file mode 100644 index 0000000000..66d06866c8 --- /dev/null +++ b/test/units/testsuite-59.service @@ -0,0 +1,6 @@ +[Unit] +Description=TEST-59-RELOADING-RESTART + +[Service] +Type=oneshot +ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh diff --git a/test/units/testsuite-59.sh b/test/units/testsuite-59.sh new file mode 100755 index 0000000000..459d6e6403 --- /dev/null +++ b/test/units/testsuite-59.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +set -eux +set -o pipefail + +fail () { + systemd-analyze log-level info + exit 1 +} + +# Wait for a service to enter a state within a timeout period, if it doesn't +# enter the desired state within the timeout period then this function will +# exit the test case with a non zero exit code. +wait_on_state_or_fail () { + service=$1 + expected_state=$2 + timeout=$3 + + state=$(systemctl show "$service" --property=ActiveState --value) + while [ "$state" != "$expected_state" ]; do + if [ "$timeout" = "0" ]; then + fail + fi + timeout=$((timeout - 1)) + sleep 1 + state=$(systemctl show "$service" --property=ActiveState --value) + done +} + +systemd-analyze log-level debug +systemd-analyze log-target console + + +cat >/run/systemd/system/testservice-fail-59.service </run/systemd/system/testservice-fail-restart-59.service </run/systemd/system/testservice-abort-restart-59.service </testok + +exit 0