diff options
-rw-r--r-- | src/comp.c | 65 | ||||
-rw-r--r-- | src/pies.c | 3 | ||||
-rw-r--r-- | src/pies.h | 8 | ||||
-rw-r--r-- | src/progman.c | 47 | ||||
-rw-r--r-- | src/socket.c | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 9 | ||||
-rw-r--r-- | tests/atlocal.in | 2 | ||||
-rwxr-xr-x | tests/aux/mailer (renamed from tests/mailer) | 0 | ||||
-rwxr-xr-x | tests/aux/respawn (renamed from tests/respawn) | 0 | ||||
-rwxr-xr-x | tests/aux/retcode (renamed from tests/retcode) | 0 | ||||
-rwxr-xr-x | tests/aux/startup | 7 | ||||
-rw-r--r-- | tests/redirect.at | 2 | ||||
-rw-r--r-- | tests/respawn.at | 2 | ||||
-rw-r--r-- | tests/ret-exec.at | 4 | ||||
-rw-r--r-- | tests/ret-notify.at | 6 | ||||
-rw-r--r-- | tests/startup.at | 84 | ||||
-rw-r--r-- | tests/testsuite.at | 1 |
17 files changed, 213 insertions, 31 deletions
@@ -25,4 +25,9 @@ struct complist }; +/* 0 on the first load, and 1 on all subsequent reloads. Tells the + component_config_commit whether we're starting from scratch or just + updating an already loaded configuration */ +static int loaded; + static struct complist comp_list[2]; static int cur; @@ -33,5 +38,5 @@ static size_t comp_count; static pies_depmap_t depmap; -static int +static inline int next_index (void) { @@ -39,5 +44,5 @@ next_index (void) } -static int +static inline int prev_index (void) { @@ -86,4 +91,20 @@ component_append (struct component *comp) void +comp_array_remove (size_t i) +{ + struct component *comp = comp_array[i]; + + depmap_remove (depmap, i); + while (i < comp_count -1) + { + comp_array[i] = comp_array[i+1]; + comp_array[i]->arridx = i; + i++; + } + component_free (comp); + comp_count--; +} + +void component_unlink (struct component *comp) { @@ -202,6 +223,11 @@ component_ref_decr (struct component *comp) assert (comp->ref_count > 0); if (--comp->ref_count == 0) + { + if (component_is_active (comp)) + comp_array_remove (comp->arridx); + else component_free (comp); } +} static int @@ -426,15 +452,4 @@ report_cyclic_dependency (pies_depmap_t dp, size_t idx) void -comp_array_remove (size_t i) -{ - struct component *comp = comp_array[i]; - if (i < comp_count - 1) - memmove (&comp_array[i], &comp_array[i+1], - (comp_count - i - 1) * sizeof comp_array[0]); - component_free (comp); - comp_count--; -} - -void component_build_depmap (void) { @@ -461,5 +476,4 @@ component_build_depmap (void) comp->tag, tag); comp_array_remove (i); - depmap_remove (depmap, i); continue; } @@ -498,8 +512,5 @@ component_build_depmap (void) for (i = 0; i < comp_count;) if (comp_array[i]->flags & CF_REMOVE) - { comp_array_remove (i); - depmap_remove (depmap, i); - } else i++; @@ -529,6 +540,15 @@ component_config_commit (void) comp_count = i; - /* Rearrange components, registering prog entries for the new ones */ - for (comp = list->head, i = 0; comp; comp = comp->next, i++) + /* Rearrange components, registering entries for the new ones */ + for (comp = list->head, i = 0; comp; ) + { + struct component *next = comp->next; + if (loaded && comp->mode == pies_comp_startup) + { + /* Ignore startup components */ + component_unlink (comp); + component_free (comp); + } + else { match = complist_find_match (prev, comp); @@ -544,5 +564,10 @@ component_config_commit (void) comp_array[i] = comp; comp->arridx = i; + i++; + } + comp = next; } + /* Adjust comp_count */ + comp_count = i; /* Mark orphaned progs for termination */ @@ -561,4 +586,6 @@ component_config_commit (void) if (!comp->prog) register_prog (comp); + + loaded = 1; } @@ -821,4 +821,6 @@ static struct tokendef modetab[] = { {"pass-fd", pies_comp_pass_fd}, {"pass", pies_comp_pass_fd}, + {"startup", pies_comp_startup}, + {"shutdown", pies_comp_shutdown}, {"boot", pies_comp_boot}, {"bootwait", pies_comp_boot}, @@ -2229,4 +2231,5 @@ main (int argc, char **argv) progman_create_sockets (); + program_init_startup (); progman_start (); @@ -139,4 +139,11 @@ enum pies_comp_mode pies_comp_pass_fd, + /* Components of this type runs once on program startup. Running other + components is delayed until the last startup component finishes. */ + pies_comp_startup, + + /* FIXME: Runs before program termination */ + pies_comp_shutdown, + /* ** Init-style components @@ -335,4 +342,5 @@ int pies_reread_config (void); void register_prog (struct component *comp); +void program_init_startup (void); int progman_waiting_p (void); void progman_start (void); diff --git a/src/progman.c b/src/progman.c index 1b09cd5..5bc4eb3 100644 --- a/src/progman.c +++ b/src/progman.c @@ -318,4 +318,17 @@ register_command (char *tag, char *command, pid_t pid) } +static inline int +progman_startup_phase (void) +{ + struct prog *prog; + + for (prog = proghead; prog; prog = prog->next) + { + if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup) + return 1; + } + return 0; +} + int progman_waiting_p (void) @@ -325,5 +338,7 @@ progman_waiting_p (void) for (prog = proghead; prog; prog = prog->next) { - if (IS_COMPONENT (prog) && prog->wait && prog->pid > 0) + if (IS_COMPONENT (prog) + && prog->pid > 0 + && (prog->wait || prog->v.p.comp->mode == pies_comp_startup)) { debug (3, ("%s: waiting for %s (%lu)", @@ -1527,4 +1542,23 @@ progman_recompute_alarm (void) void +program_init_startup (void) +{ + struct prog *prog; + + for (prog = proghead; prog; prog = prog->next) + if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup) + { + debug (1, ("running startup components")); + break; + } + + for (; prog; prog = prog->next) + if (IS_COMPONENT (prog) && prog->v.p.comp->mode == pies_comp_startup) + { + prog_start (prog); + } +} + +void progman_start (void) { @@ -1532,5 +1566,6 @@ progman_start (void) if (progman_waiting_p ()) - /* Noting to do if there are processes left in the previous runlevel */ + /* Noting to do if there are processes left in the previous runlevel + (in sysv-init mode) or startup components running. */ return; @@ -2322,4 +2357,12 @@ progman_cleanup (int expect_term) destroy_prog (&prog); } + else if (prog->v.p.comp->mode == pies_comp_startup) + { + debug (1, (_("removing startup component %s, pid=%lu"), + prog_tag (prog), (unsigned long)pid)); + destroy_prog (&prog); + if (!progman_startup_phase ()) + pies_schedule_children (PIES_CHLD_WAKEUP); + } else { diff --git a/src/socket.c b/src/socket.c index aa01543..40c7aa7 100644 --- a/src/socket.c +++ b/src/socket.c @@ -25,4 +25,6 @@ switch_eids (uid_t *puid, gid_t *pgid, mode_t *pumask) mode_t omask = umask (*pumask); + if ((*puid && *puid != ouid) || (*pgid && *pgid != ogid)) + { if (setegid (*pgid)) logmsg (LOG_ERR, _("cannot switch to EGID %lu: %s"), @@ -31,4 +33,5 @@ switch_eids (uid_t *puid, gid_t *pgid, mode_t *pumask) logmsg (LOG_ERR, _("cannot switch to EUID %lu: %s"), (unsigned long) *puid, strerror (errno)); + } *puid = ouid; *pgid = ogid; @@ -638,3 +641,2 @@ pies_pause (void) } } - diff --git a/tests/Makefile.am b/tests/Makefile.am index 447104b..b2f2719 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -15,5 +15,11 @@ # along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. -EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 respawn retcode mailer +AUXTOOLS = \ + aux/respawn\ + aux/retcode\ + aux/mailer\ + aux/startup + +EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 $(AUXTOOLS) DISTCLEANFILES = atconfig $(check_SCRIPTS) MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) @@ -47,4 +53,5 @@ TESTSUITE_AT = \ ret-exec.at\ ret-notify.at\ + startup.at\ version.at diff --git a/tests/atlocal.in b/tests/atlocal.in index 9069bbd..1992b80 100644 --- a/tests/atlocal.in +++ b/tests/atlocal.in @@ -5,5 +5,5 @@ PATH=@abs_builddir@:@abs_top_builddir@/src:$srcdir:$PATH XFAILFILE=$abs_builddir/.badversion - +auxdir="$abs_srcdir/aux" trimws() { sed 's/[ ][ ]*$//' diff --git a/tests/mailer b/tests/aux/mailer index f832ff5..f832ff5 100755 --- a/tests/mailer +++ b/tests/aux/mailer diff --git a/tests/respawn b/tests/aux/respawn index 11d59f6..11d59f6 100755 --- a/tests/respawn +++ b/tests/aux/respawn diff --git a/tests/retcode b/tests/aux/retcode index b827ba9..b827ba9 100755 --- a/tests/retcode +++ b/tests/aux/retcode diff --git a/tests/aux/startup b/tests/aux/startup new file mode 100755 index 0000000..b9d92a3 --- /dev/null +++ b/tests/aux/startup @@ -0,0 +1,7 @@ +#!/bin/sh +dir=${1:?} +time=${2:?} +tag=${3:?} + +touch $dir/$tag +sleep $time diff --git a/tests/redirect.at b/tests/redirect.at index 9e53ba2..3a8cca7 100644 --- a/tests/redirect.at +++ b/tests/redirect.at @@ -25,5 +25,5 @@ cat > pies.conf <<_EOT component test { mode respawn; - command "$abs_srcdir/respawn -tag respawn -append -pid $comp_pid_file"; + command "$auxdir/respawn -tag respawn -append -pid $comp_pid_file"; stdout file "$outfile"; } diff --git a/tests/respawn.at b/tests/respawn.at index 8d72c40..4a8e3a7 100644 --- a/tests/respawn.at +++ b/tests/respawn.at @@ -24,5 +24,5 @@ cat > pies.conf <<_EOT component test { mode respawn; - command "$abs_srcdir/respawn -append -pid $comp_pid_file"; + command "$auxdir/respawn -append -pid $comp_pid_file"; } _EOT diff --git a/tests/ret-exec.at b/tests/ret-exec.at index bf2c1a4..0b3d716 100644 --- a/tests/ret-exec.at +++ b/tests/ret-exec.at @@ -27,8 +27,8 @@ component test { mode respawn; return-code 10 { - exec "$abs_srcdir/retcode $report_file"; + exec "$auxdir/retcode $report_file"; action disable; } - command "$abs_srcdir/respawn -sleep 2 -pid $comp_pid_file -exit 10"; + command "$auxdir/respawn -sleep 2 -pid $comp_pid_file -exit 10"; } _EOT diff --git a/tests/ret-notify.at b/tests/ret-notify.at index d1a7f39..a7768aa 100644 --- a/tests/ret-notify.at +++ b/tests/ret-notify.at @@ -23,6 +23,6 @@ PIES_CONTROL_INIT report_file=$PWD/report cat > pies.conf <<_EOT -mailer-program "$abs_srcdir/mailer"; -mailer-command-line "$abs_srcdir/mailer $report_file"; +mailer-program "$auxdir/mailer"; +mailer-command-line "$auxdir/mailer $report_file"; component test { mode respawn; @@ -31,5 +31,5 @@ component test { action disable; } - command "$abs_srcdir/respawn -sleep 2 -exit 10"; + command "$auxdir/respawn -sleep 2 -exit 10"; } _EOT diff --git a/tests/startup.at b/tests/startup.at new file mode 100644 index 0000000..72017ce --- /dev/null +++ b/tests/startup.at @@ -0,0 +1,84 @@ +# This file is part of GNU pies testsuite. -*- Autotest -*- +# Copyright (C) 2019 Sergey Poznyakoff +# +# GNU pies is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU pies is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU pies. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([Startup components]) + +AT_CHECK([ +PIES_XFAIL_CHECK +PIES_CONTROL_INIT +comp_pid_file=$PWD/comp.pid + +cat > pies.conf <<_EOT +component b1 { + mode startup; + command "$auxdir/startup $PWD 1 b1"; +} + +component b2 { + mode startup; + command "$auxdir/startup $PWD 2 b2"; +} + +component test { + mode respawn; + command "$auxdir/respawn -append -pid $comp_pid_file"; +} +_EOT + +pies --config-file control.conf --config-file pies.conf + +n=0 +res= +b1= +b2= +while : +do + echo "n=$n" >> tracefile + if test -z "$b1" && test -f b1; then + res="${res}b1" + b1=1 + echo "got b1" >> tracefile + fi + if test -z "$b2" && test -f b2; then + res="${res}b2" + b2=1 + echo "got b2" >> tracefile + fi + if test -f $comp_pid_file; then + echo "got pidfile" >> tracefile + res="${res}pid" + break + fi + sleep 1 + n=$(($n + 1)) + if test $n -gt 10; then + echo >&2 "timed out" + break + fi +done + +PIES_STOP +case $res in +b1b2pid|b2b1pid) echo b1b2pid;; +*) echo $res +esac +], +[0], +[b1b2pid +]) + +AT_CLEANUP + diff --git a/tests/testsuite.at b/tests/testsuite.at index 03ddd50..2a1167d 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -66,2 +66,3 @@ m4_include([redirect.at]) m4_include([ret-exec.at]) m4_include([ret-notify.at]) +m4_include([startup.at]) |