diff --git a/test/Makefile.am b/test/Makefile.am index 8b072f45..82740a98 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -24,6 +24,7 @@ EXTRA_DIST += cond-start-task.sh EXTRA_DIST += failing-sysv.sh EXTRA_DIST += global-envs.sh EXTRA_DIST += pre-post-serv.sh +EXTRA_DIST += restart-self.sh EXTRA_DIST += runlevel.sh EXTRA_DIST += start-stop-service.sh EXTRA_DIST += start-stop-service-sub-config.sh @@ -52,6 +53,7 @@ TESTS += cond-start-task.sh TESTS += failing-sysv.sh TESTS += global-envs.sh TESTS += pre-post-serv.sh +TESTS += restart-self.sh TESTS += runlevel.sh TESTS += start-stop-service.sh TESTS += start-stop-service-sub-config.sh diff --git a/test/common/serv.c b/test/common/serv.c index ba7057b1..4d033609 100644 --- a/test/common/serv.c +++ b/test/common/serv.c @@ -47,6 +47,28 @@ static void verify_noenv(char *key) errx(1, "Error, key %s is set in environment to '%s'", key, val); } +static void inc_restarts(void) +{ + char buf[10]; + int cnt = 0; + FILE *fp; + + fp = fopen("/tmp/serv-restart.cnt", "r+"); + if (!fp) { + fp = fopen("/tmp/serv-restart.cnt", "w"); + if (!fp) + err(1, "failed creating restart counter file"); + } else { + if (fgets(buf, sizeof(buf), fp)) + cnt = atoi(buf); + } + cnt++; + + fseek(fp, SEEK_SET, 0); + fprintf(fp, "%d", cnt); + fclose(fp); +} + static void sig(int signo) { warnx("We got signal %d ...", signo); @@ -86,6 +108,7 @@ static int usage(int rc) " -n Run in foreground\n" " -p Create PID file despite running in foreground\n" " -P FILE Create PID file using FILE\n" + " -r SVC Call initctl to restart service SVC (self)\n" "\n" "By default this program daemonizes itself to the background, and,\n" "when it's done setting up its signal handler(s), creates a PID file\n" @@ -100,10 +123,12 @@ int main(int argc, char *argv[]) { int do_background = 1; int do_pidfile = 1; + int do_restart = 0; char *pidfn = NULL; + char cmd[80]; int c; - while ((c = getopt(argc, argv, "e:E:hnpP:")) != EOF) { + while ((c = getopt(argc, argv, "e:E:hnpP:r:")) != EOF) { switch (c) { case 'h': return usage(0); @@ -123,6 +148,10 @@ int main(int argc, char *argv[]) case 'P': pidfn = optarg; break; + case 'r': + snprintf(cmd, sizeof(cmd), "initctl restart %s", optarg); + do_restart = 1; + break; default: return usage(1); } @@ -142,8 +171,15 @@ int main(int argc, char *argv[]) pidfile(pidfn); warnx("Entering while(1) loop"); - while (1) + while (1) { sleep(1); + if (do_restart) { + inc_restarts(); + if (system(cmd)) + return 1; + break; + } + } warnx("Leaving ..."); return 0; diff --git a/test/restart-self.sh b/test/restart-self.sh new file mode 100755 index 00000000..fef8f010 --- /dev/null +++ b/test/restart-self.sh @@ -0,0 +1,47 @@ +#!/bin/sh +# Verify that a service can restart itself, issue #280 +set -eu + +TEST_DIR=$(dirname "$0") + +test_setup() +{ + say "Test start $(date)" + texec sh -c "mkdir -p /etc/default" +} + +test_teardown() +{ + say "Test done $(date)" + say "Running test teardown." + + texec rm -f "$FINIT_CONF" +} + +check_restarts() +{ + assert "serv restarts" "$(texec cat "$1" | awk '{print $1;}')" -ge "$2" +} + + +# shellcheck source=/dev/null +. "$TEST_DIR/tenv/lib.sh" + +say "Add stanza to $FINIT_CONF" +texec sh -c "echo 'service serv -np -r serv -- Restart self' > $FINIT_CONF" + +say 'Reload Finit' +texec sh -c "initctl reload" + +sleep 2 +texec sh -c "initctl status serv" +texec sh -c "ps" + +sleep 2 +texec sh -c "initctl status serv" +texec sh -c "ps" + +say 'Pending restarts by itself ...' +retry 'check_restarts /tmp/serv-restart.cnt 3' 20 1 + +return 0