mirror of
https://github.com/troglobit/finit.git
synced 2026-09-30 13:02:37 +07:00
test: extend start-stop-serv test w/ all supported combinations
serv: add support for foregrounding, running with and without PID file,
including custom PID filename.
test: verify Finit can start & monitor services that:
1) Fork and creates a PID file in a known location
2) Don't fork and don't create a PID file, but Finit does
3) Don't fork but create a PID file
4) Don't fork and create custom named PID file
Note: Finit cannot support a service that forks and doesn't create a PID
file. This combination is impossible to support without tracking
all processes created in /proc -- which Finit does not do atm.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+68
-13
@@ -1,4 +1,9 @@
|
||||
/* Basic forking UNIX daemon with no options to run in foreground */
|
||||
/*
|
||||
* Basic UNIX daemon
|
||||
*
|
||||
* Options to run in foreground and to create a PID file. When running
|
||||
* in foregrund it does not create a PID file by default.
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <paths.h>
|
||||
@@ -8,43 +13,93 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PROGNM "serv"
|
||||
|
||||
static void sig(int signo)
|
||||
{
|
||||
warnx("We got signal %d ...", signo);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void pidfile(char *nm)
|
||||
static void pidfile(char *pidfn)
|
||||
{
|
||||
char fn[80];
|
||||
pid_t pid;
|
||||
FILE *fp;
|
||||
|
||||
if (!nm)
|
||||
nm = "serv";
|
||||
|
||||
snprintf(fn, sizeof(fn), "%s%s.pid", _PATH_VARRUN, nm);
|
||||
if (!pidfn) {
|
||||
snprintf(fn, sizeof(fn), "%s%s.pid", _PATH_VARRUN, PROGNM);
|
||||
pidfn = fn;
|
||||
}
|
||||
pid = getpid();
|
||||
warnx("Creating PID file %s with %d", fn, pid);
|
||||
warnx("Creating PID file %s with %d", pidfn, pid);
|
||||
|
||||
fp = fopen(fn, "w");
|
||||
fp = fopen(pidfn, "w");
|
||||
if (!fp)
|
||||
exit(1);
|
||||
fprintf(fp, "%d\n", pid);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
static int usage(int rc)
|
||||
{
|
||||
FILE *fp = rc ? stderr : stdout;
|
||||
|
||||
fprintf(fp,
|
||||
"%s [-nhp] [-P FILE]\n"
|
||||
"\n"
|
||||
" -n Run in foreground\n"
|
||||
" -h Show help text (this)\n"
|
||||
" -p Create PID file despite running in foreground\n"
|
||||
" -P FILE Create PID file using FILE\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"
|
||||
"to let the rest of the system know it's done. When the program runs\n"
|
||||
"in the foreground it does not create a PID file by default.\n",
|
||||
PROGNM);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int do_background = 1;
|
||||
int do_pidfile = 1;
|
||||
char *pidfn = NULL;
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "hnpP:")) != EOF) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
return usage(0);
|
||||
case 'n':
|
||||
do_background = 0;
|
||||
do_pidfile--;
|
||||
break;
|
||||
case 'p':
|
||||
do_pidfile++;
|
||||
break;
|
||||
case 'P':
|
||||
pidfn = optarg;
|
||||
break;
|
||||
default:
|
||||
return usage(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Daemonize, fork to background etc. */
|
||||
if (daemon(0, 1))
|
||||
return 1;
|
||||
if (do_background) {
|
||||
if (daemon(0, 1))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Signal handlers first *then* PID file */
|
||||
signal(SIGTERM, sig);
|
||||
|
||||
/* Tell finit where we really are */
|
||||
pidfile(NULL);
|
||||
/* Tell world where we are, but not if bg w/o pid file */
|
||||
if (do_pidfile == 1)
|
||||
pidfile(pidfn);
|
||||
|
||||
warnx("Entering while(1) loop");
|
||||
while (1)
|
||||
|
||||
+42
-25
@@ -1,11 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -eu
|
||||
|
||||
TEST_DIR=$(dirname "$0")
|
||||
|
||||
# shellcheck source=/dev/null
|
||||
. "$TEST_DIR/tenv/lib.sh"
|
||||
test_setup()
|
||||
{
|
||||
say "Test start $(date)"
|
||||
cp "$TENV_ROOT"/../common/serv "$TENV_ROOT"/test_assets/
|
||||
}
|
||||
|
||||
test_teardown()
|
||||
{
|
||||
@@ -16,35 +18,50 @@ test_teardown()
|
||||
texec rm -f /test_assets/serv
|
||||
}
|
||||
|
||||
say "Test start $(date)"
|
||||
test_one()
|
||||
{
|
||||
pidfn=$1
|
||||
service=$2
|
||||
|
||||
cp "$TENV_ROOT"/../common/serv "$TENV_ROOT"/test_assets/
|
||||
say "Add service stanza '$service' to $FINIT_CONF ..."
|
||||
texec sh -c "echo '$service' > $FINIT_CONF"
|
||||
|
||||
say "Add service stanza in $FINIT_CONF"
|
||||
texec sh -c "echo 'service [2345] pid:!/run/serv.pid /test_assets/serv -- Forking service' > $FINIT_CONF"
|
||||
say 'Reload Finit'
|
||||
#texec sh -c "initctl debug"
|
||||
texec sh -c "initctl reload"
|
||||
#texec sh -c "initctl status"
|
||||
#texec sh -c "ps"
|
||||
|
||||
say 'Reload Finit'
|
||||
#texec sh -c "initctl debug"
|
||||
texec sh -c "initctl reload"
|
||||
#texec sh -c "initctl status"
|
||||
#texec sh -c "ps"
|
||||
#texec sh -c "initctl status"
|
||||
#texec sh -c "ps"
|
||||
#texec sh -c "initctl status serv"
|
||||
|
||||
# Wait for process to fork, create its PID file so Finit can register
|
||||
# its new PID -- this is the major difference from regular services.
|
||||
sleep 2
|
||||
retry 'assert_num_children 1 serv'
|
||||
retry "assert_pidfile $pidfn" 1
|
||||
|
||||
#texec sh -c "initctl status"
|
||||
#texec sh -c "ps"
|
||||
#texec sh -c "initctl status serv"
|
||||
say 'Stop the service'
|
||||
texec sh -c "initctl stop serv"
|
||||
|
||||
retry 'assert_num_children 1 serv'
|
||||
retry 'assert_num_children 0 serv'
|
||||
|
||||
say 'Stop the service'
|
||||
texec sh -c "initctl stop serv"
|
||||
say 'Start the service again'
|
||||
texec sh -c "initctl start serv"
|
||||
|
||||
retry 'assert_num_children 0 serv'
|
||||
retry 'assert_num_children 1 serv'
|
||||
|
||||
say 'Start the service again'
|
||||
texec sh -c "initctl start serv"
|
||||
say "Done, drop service from $FINIT_CONF ..."
|
||||
texec sh -c "rm $FINIT_CONF"
|
||||
texec sh -c "initctl reload"
|
||||
}
|
||||
|
||||
retry 'assert_num_children 1 serv'
|
||||
# shellcheck source=/dev/null
|
||||
. "$TEST_DIR/tenv/lib.sh"
|
||||
|
||||
test_one "/run/serv.pid" "service pid:!/run/serv.pid /test_assets/serv -- Forking service"
|
||||
# This one could never be started by and monitored by Finit: it forks to
|
||||
# background and does not create a PID file. Essentially it's lost to
|
||||
# Finit, and any other sane process monitor.
|
||||
#test_one "/run/serv.pid" "service pid:/run/serv.pid /test_assets/serv -p -- Forking service w/o PID file"
|
||||
test_one "/run/serv.pid" "service pid:/run/serv.pid /test_assets/serv -n -- Foreground service w/o PID file"
|
||||
test_one "/run/serv.pid" "service /test_assets/serv -n -p -- Foreground service w/ PID file"
|
||||
test_one "/run/servy.pid" "service pid:/run/servy.pid /test_assets/serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file"
|
||||
|
||||
@@ -32,6 +32,12 @@ assert_new_pid()
|
||||
assert "Finit has registered new PID" "$(texec initctl |grep $1 |awk '{print $1}')" -eq "$(texec cat $2)"
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
assert_pidfile()
|
||||
{
|
||||
assert "Process has PID file" "$(texec find $1 2>/dev/null)"
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2154
|
||||
texec()
|
||||
{
|
||||
@@ -157,6 +163,10 @@ log "$color_reset" 'Setup of test environment done' ''
|
||||
|
||||
finit_pid=$(retry "pgrep -P $finit_ppid")
|
||||
|
||||
if type test_setup > /dev/null 2>&1 ; then
|
||||
test_setup
|
||||
fi
|
||||
|
||||
#tty=/dev/$(texec cat /sys/class/tty/console/active)
|
||||
#texec cat "$tty" &
|
||||
#sleep 1
|
||||
|
||||
Reference in New Issue
Block a user