diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2026-01-24 08:12:42 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2026-01-24 08:12:42 +0000 |
| commit | dbaaee871996024e083bbdb83de85f8c287ee999 (patch) | |
| tree | 4dc7ac412d4969de71212c95e008d4c374a180b4 | |
| parent | 38e8fd341f427a1395c1d5869d69eb67a3c24698 (diff) | |
| download | s6-rc-dbaaee871996024e083bbdb83de85f8c287ee999.tar.gz | |
Support bringing down essential services in s6-rc-update
Also adjust verbosity of s6-rc-compile
| -rw-r--r-- | doc/s6-rc-update.html | 40 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-compile.c | 3 | ||||
| -rw-r--r-- | src/s6-rc/s6-rc-update.c | 101 |
3 files changed, 90 insertions, 54 deletions
diff --git a/doc/s6-rc-update.html b/doc/s6-rc-update.html index d0182c2..b3ad96a 100644 --- a/doc/s6-rc-update.html +++ b/doc/s6-rc-update.html @@ -75,34 +75,46 @@ live compiled service database. </li> <h2> Options </h2> +<dl> <ul> - <li> <tt>-n</tt> : dry run. s6-rc-update will compute the service + <dt> -n, --dry-run </dt> + <dd> Dry run. s6-rc-update will compute the service transitions, and print the <a href="s6-rc.html">s6-rc</a> command lines it would execute to perform those transitions. It will not actually -run them or modify the live database. </li> - <li> <tt>-v <em>verbosity</em></tt> : be more or less +run them or modify the live database. </dd> + <dt> -v <em>verbosity</em>, --verbosity=<em>verbosity</em> </dt> + <dd> Be more or less verbose. Default is 1: warning and error messages will be printed to stderr. 0 silences warnings. 2 adds a bit more information about -what s6-rc-update is doing. 3 or more is heavy debug output. </li> - <li> <tt>-t <em>timeout</em></tt> : if s6-rc-update cannot +what s6-rc-update is doing. 3 or more is heavy debug output. </dd> + <dt> -t <em>timeout</em>, --timeout=<em>timeout</em> </dt> + <dd> If s6-rc-update cannot perform its job within <em>timeout</em> milliseconds, it will exit. The default is 0, meaning infinite (no timeout). Be aware that timing out and exiting may leave the live database in an inconsistent state, -so use of this option is not recommended. </li> - <li> <tt>-l <em>live</em></tt> : look for the -live state in <em>live</em>. It must be an absolute path. +so use of this option is not recommended. </dd> + <dt> -l <em>live</em>, --livedir=<em>live</em> </dt> + <dd> Look for the live state in <em>live</em>. It must be an absolute path. Default is <tt>/run/s6-rc</tt>. The default can be changed at compile-time by giving the -<tt>--livedir=<em>live</em></tt> option to <tt>./configure</tt>. </li> - <li> <tt>-f <em>convfile</em></tt> : use the conversion +<tt>--livedir=<em>live</em></tt> option to <tt>./configure</tt>. </dd> + <dt> -f <em>convfile</em>, --conversion-file=<em>convfile</em> </dt> + <dd> Use the conversion file located at <em>convfile</em>. Default is <tt>/dev/null</tt>, -meaning no special instructions. </li> - <li> <tt>-b</tt> : blocking lock. If the database is currently +meaning no special instructions. </dd> + <dt> -b, --block </dt> + <dd> Blocking lock. If the database is currently being used by another program, s6-rc-update will wait until that other program has released its lock on the database, then proceed. By default, s6-rc-update fails with an error message if the database -is currently in use. </li> -</ul> +is currently in use. </dd> + <dt> -E, --no-force-essentials </dt> + <dd> If essential services are scheduled to be stopped for the transition, +ignore them, i.e. keep them alive. This is the default. </dd> + <dt> -e, --force-essentials </dt> + <dd> If essential services are scheduled to be stopped for the transition, +stop them just like any other service. </dd> +</dl> <h2> Transition details </h2> diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c index 6bc59ed..b9b6955 100644 --- a/src/s6-rc/s6-rc-compile.c +++ b/src/s6-rc/s6-rc-compile.c @@ -545,7 +545,7 @@ static inline void add_bundle (before_t *be, int dfd, char const *srcdir, char c static inline void add_source (before_t *be, int dfd, char const *srcdir, char const *name) { - if (verbosity >= 2) strerr_warni4x("parsing ", srcdir, "/", name) ; + if (verbosity >= 3) strerr_warni4x("parsing ", srcdir, "/", name) ; switch (type_check(dfd)) { case 0 : strerr_dief6x(1, "invalid ", srcdir, "/", name, "/type", ": must be oneshot, longrun, or bundle") ; @@ -562,6 +562,7 @@ static inline void add_sources (before_t *be, char const *srcdir, stralloc *sa) int fdsrc ; DIR *dir = opendir(srcdir) ; if (!dir) strerr_diefu2sys(111, "opendir ", srcdir) ; + if (verbosity >= 2) strerr_warni("adding sources from ", srcdir) ; fdsrc = dir_fd(dir) ; for (;;) { diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c index 82f2a6e..0b7a053 100644 --- a/src/s6-rc/s6-rc-update.c +++ b/src/s6-rc/s6-rc-update.c @@ -13,15 +13,13 @@ #include <skalibs/types.h> #include <skalibs/allreadwrite.h> #include <skalibs/buffer.h> -#include <skalibs/strerr.h> -#include <skalibs/sgetopt.h> +#include <skalibs/envexec.h> #include <skalibs/bitarray.h> #include <skalibs/cdb.h> #include <skalibs/stralloc.h> #include <skalibs/tai.h> #include <skalibs/cspawn.h> #include <skalibs/djbunix.h> -#include <skalibs/exec.h> #include <skalibs/skamisc.h> #include <skalibs/unix-transactional.h> @@ -37,7 +35,7 @@ #include <skalibs/posixishard.h> -#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] [ -f conversion_file ] [ -b ] newdb" +#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] [ -f conversion_file ] [ -E | -e ] [ -b ] newdb" #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "build string") ; @@ -560,36 +558,61 @@ static unsigned int want_count (unsigned char const *state, unsigned int n) return count ; } +enum golb_e +{ + GOLB_DRYRUN = 0x01, + GOLB_BLOCK = 0x02, + GOLB_FORCEESSENTIALS = 0x04, +} ; + +enum gola_e +{ + GOLA_VERBOSITY, + GOLA_TIMEOUT, + GOLA_LIVEDIR, + GOLA_CONVFILE, + GOLA_N +} ; + int main (int argc, char const *const *argv, char const *const *envp) { - char const *convfile = "/dev/null" ; - tain deadline ; - int dryrun = 0 ; - int blocking = 0 ; + static gol_bool const rgolb[] = + { + { .so = 'n', .lo = "dry-run", .clear = 0, .set = GOLB_DRYRUN }, + { .so = 'b', .lo = "block", .clear = 0, .set = GOLB_BLOCK }, + { .so = 'E', .lo = "no-force-essentials", .clear = GOLB_FORCEESSENTIALS, .set = 0 }, + { .so = 'e', .lo = "force-essentials", .clear = 0, .set = GOLB_FORCEESSENTIALS }, + } ; + static gol_arg const rgola[] = + { + { .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY }, + { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT }, + { .so = 'l', .lo = "livedir", .i = GOLA_LIVEDIR }, + { .so = 'f', .lo = "conversion-file", .i = GOLA_CONVFILE }, + } ; + uint64_t wgolb = 0 ; + char const *wgola[GOLA_N] = { 0 } ; + tain deadline = TAIN_INFINITE_RELATIVE ; PROG = "s6-rc-update" ; + wgola[GOLA_CONVFILE] = "/dev/null" ; + { - unsigned int t = 0 ; - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "v:t:nl:f:b", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; - case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; - case 'n' : dryrun = 1 ; break ; - case 'l' : live = l.arg ; break ; - case 'f' : convfile = l.arg ; break ; - case 'b' : blocking = 1 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; + unsigned int golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + if (!argc) dieusage() ; + } + + if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) + strerr_dief1x(100, "verbosity must be an unsigned integer") ; + if (wgola[GOLA_TIMEOUT]) + { + unsigned int t ; + if (!uint0_scan(wgola[GOLA_TIMEOUT], &t)) + strerr_dief1x(100, "verbosity must be an unsigned integer") ; if (t) tain_from_millisecs(&deadline, t) ; - else deadline = tain_infinite_relative ; } - if (!argc) dieusage() ; + if (wgola[GOLA_LIVEDIR]) live = wgola[GOLA_LIVEDIR] ; + if (live[0] != '/') strerr_dief2x(100, live, " is not an absolute path") ; if (argv[0][0] != '/') @@ -615,9 +638,9 @@ int main (int argc, char const *const *argv, char const *const *envp) memcpy(dbfn, live, livelen) ; memcpy(dbfn + livelen, "/compiled", 10) ; - if (!s6rc_lock(live, 2, &livelock, dbfn, 1, &oldlock, blocking)) + if (!s6rc_lock(live, 2, &livelock, dbfn, 1, &oldlock, !!(wgolb & GOLB_BLOCK))) strerr_diefu4sys(111, "take lock on ", live, " and ", dbfn) ; - if (!s6rc_lock(0, 0, 0, argv[0], 1, &newlock, blocking)) + if (!s6rc_lock(0, 0, 0, argv[0], 1, &newlock, !!(wgolb & GOLB_BLOCK))) strerr_diefu2sys(111, "take lock on ", argv[0]) ; @@ -705,7 +728,7 @@ int main (int argc, char const *const *argv, char const *const *envp) /* Read the conversion file and compute what to do */ if (verbosity >= 2) strerr_warni1x("computing state adjustments") ; - compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, invimage, fdnewc, argv[0], &newdb, &sa) ; + compute_transitions(wgola[GOLA_CONVFILE], oldstate, fdoldc, &olddb, newstate, invimage, fdnewc, argv[0], &newdb, &sa) ; tain_now_g() ; if (!tain_future(&deadline)) strerr_dief1x(10, "timed out while computing state adjutments") ; @@ -713,14 +736,14 @@ int main (int argc, char const *const *argv, char const *const *envp) /* Down transition */ { - char const *newargv[12 + (dryrun * 4) + want_count(oldstate, oldn)] ; + char const *newargv[12 + (!!(wgolb & GOLB_DRYRUN) * 4) + want_count(oldstate, oldn)] ; unsigned int m = 0, i = oldn ; int wstat ; char vfmt[UINT_FMT] ; char tfmt[UINT_FMT] ; vfmt[uint_fmt(vfmt, verbosity)] = 0 ; fill_tfmt(tfmt, &deadline) ; - if (dryrun) + if (wgolb & GOLB_DRYRUN) { newargv[m++] = S6RC_BINPREFIX "s6-rc-dryrun" ; newargv[m++] = "-v" ; @@ -735,8 +758,8 @@ int main (int argc, char const *const *argv, char const *const *envp) newargv[m++] = tfmt ; newargv[m++] = "-l" ; newargv[m++] = live ; - if (!dryrun) newargv[m++] = "--no-lock" ; - newargv[m++] = "-d" ; + if (!(wgolb & GOLB_DRYRUN)) newargv[m++] = "--no-lock" ; + newargv[m++] = wgolb & GOLB_FORCEESSENTIALS ? "-D" : "-d" ; newargv[m++] = "--" ; newargv[m++] = "change" ; while (i--) if (oldstate[i] & 2) @@ -756,7 +779,7 @@ int main (int argc, char const *const *argv, char const *const *envp) } } - if (!dryrun) + if (!(wgolb & GOLB_DRYRUN)) { /* Update state and service directories */ @@ -798,13 +821,13 @@ int main (int argc, char const *const *argv, char const *const *envp) /* Up transition */ { - char const *newargv[12 + (dryrun * 4) + want_count(newstate, newn)] ; + char const *newargv[12 + (!!(wgolb & GOLB_DRYRUN) * 4) + want_count(newstate, newn)] ; unsigned int m = 0, i = newn ; char vfmt[UINT_FMT] ; char tfmt[UINT_FMT] ; vfmt[uint_fmt(vfmt, verbosity)] = 0 ; fill_tfmt(tfmt, &deadline) ; - if (dryrun) + if (wgolb & GOLB_DRYRUN) { newargv[m++] = S6RC_BINPREFIX "s6-rc-dryrun" ; newargv[m++] = "-v" ; @@ -819,7 +842,7 @@ int main (int argc, char const *const *argv, char const *const *envp) newargv[m++] = tfmt ; newargv[m++] = "-l" ; newargv[m++] = live ; - if (!dryrun) newargv[m++] = "--no-lock" ; + if (!(wgolb & GOLB_DRYRUN)) newargv[m++] = "--no-lock" ; newargv[m++] = "-u" ; newargv[m++] = "--" ; newargv[m++] = "change" ; |
