diff options
-rw-r--r-- | doc/s6-rc.html | 26 | ||||
-rw-r--r-- | package/deps.mak | 2 | ||||
-rw-r--r-- | src/s6-rc/deps-exe/s6-rc | 1 | ||||
-rw-r--r-- | src/s6-rc/s6-rc.c | 120 |
4 files changed, 95 insertions, 54 deletions
diff --git a/doc/s6-rc.html b/doc/s6-rc.html index 7052b45..8aa530c 100644 --- a/doc/s6-rc.html +++ b/doc/s6-rc.html @@ -46,6 +46,7 @@ especially when asking for a state change. s6-rc help s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d ] list <em>servicenames...</em> s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d ] listall <em>servicenames...</em> + s6-rc [ -l live ] [ -b ] diff s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d ] [ -p ] [ -v <em>verbosity</em> ] [ -n <em>dryrunthrottle</em> ] [ -t timeout ] change [ <em>servicenames...</em> ] </pre> @@ -63,7 +64,8 @@ state change. </li> <ul> <li> 0: success </li> - <li> 1: some of the state transitions could not be performed </li> + <li> 1: some of the state transitions could not be performed by <tt>s6-rc change</tt>; +or a mismatch was found by <tt>s6-rc diff</tt> </li> <li> 2: timed out during state change </li> <li> 3: unknown service name in the arguments </li> <li> 4: invalid service database </li> @@ -184,6 +186,28 @@ Note that the closed selection may be a very long list of services, including the most basic ones. </li> </ul> +<h3> s6-rc diff </h3> + +<p> + Checks the consistency between s6-rc's view of the state of the longruns +it's managing, and <a href="//skarnet.org/software/s6/">s6</a>'s view. +s6-rc will print one line per service +whose s6 state fails to match what s6-rc believes: + a <tt>+</tt> character (if s6 is maintaining the service as up when s6-rc +thinks it's down) or a <tt>-</tt> character (if s6 is not trying to maintain +the service when s6-rc thinks it's up), followed by the service name. +If s6-rc finds at least one mismatch, it exits 1; else it exits 0. +</p> + +<p> + <tt>s6-rc diff</tt> normally reports nothing. Currently, the only case where +s6-rc's view can diverge from s6's view is when a service has been brought +up via a <tt>s6-rc change</tt> command, then has failed at some point with +a permanent failure - which means its +<a href="//skarnet.org/software/s6/s6-supervise.html">supervisor</a> has +stopped trying to bring it back up. +</p> + <h3> s6-rc change </h3> <p> diff --git a/package/deps.mak b/package/deps.mak index 4bbc64d..738d6b8 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -37,7 +37,7 @@ libs6rc.a.xyzzy: src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_check libs6rc.so.xyzzy: EXTRA_LIBS := -ls6 -lskarnet libs6rc.so.xyzzy: src/libs6rc/s6rc_db_check_depcycles.lo src/libs6rc/s6rc_db_check_pipelines.lo src/libs6rc/s6rc_db_check_revdeps.lo src/libs6rc/s6rc_db_read.lo src/libs6rc/s6rc_db_read_sizes.lo src/libs6rc/s6rc_db_read_uint32.lo src/libs6rc/s6rc_graph_closure.lo src/libs6rc/s6rc_livedir_prefix.lo src/libs6rc/s6rc_livedir_prefixsize.lo src/libs6rc/s6rc_lock.lo src/libs6rc/s6rc_read_uint.lo src/libs6rc/s6rc_sanitize_dir.lo src/libs6rc/s6rc_servicedir_internal.lo src/libs6rc/s6rc_servicedir_block.lo src/libs6rc/s6rc_servicedir_unblock.lo src/libs6rc/s6rc_servicedir_copy_offline.lo src/libs6rc/s6rc_servicedir_copy_online.lo src/libs6rc/s6rc_servicedir_manage.lo src/libs6rc/s6rc_servicedir_unsupervise.lo s6-rc: EXTRA_LIBS := ${TAINNOW_LIB} ${SPAWN_LIB} -s6-rc: src/s6-rc/s6-rc.o ${LIBS6RC} -lskarnet +s6-rc: src/s6-rc/s6-rc.o ${LIBS6RC} -ls6 -lskarnet s6-rc-bundle: EXTRA_LIBS := s6-rc-bundle: src/s6-rc/s6-rc-bundle.o ${LIBS6RC} -lexecline -lskarnet s6-rc-compile: EXTRA_LIBS := diff --git a/src/s6-rc/deps-exe/s6-rc b/src/s6-rc/deps-exe/s6-rc index 0850117..6b09cb7 100644 --- a/src/s6-rc/deps-exe/s6-rc +++ b/src/s6-rc/deps-exe/s6-rc @@ -1,4 +1,5 @@ ${LIBS6RC} +-ls6 -lskarnet ${TAINNOW_LIB} ${SPAWN_LIB} diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c index 90ea8e2..54cca25 100644 --- a/src/s6-rc/s6-rc.c +++ b/src/s6-rc/s6-rc.c @@ -19,10 +19,11 @@ #include <skalibs/iopause.h> #include <skalibs/unix-transactional.h> #include <s6/config.h> +#include <s6/s6-supervise.h> #include <s6-rc/config.h> #include <s6-rc/s6rc.h> -#define USAGE "s6-rc [ -v verbosity ] [ -n dryrunthrottle ] [ -t timeout ] [ -l live ] [ -b ] [ -u | -d ] [ -p ] [ -a ] help|list|listall|change [ servicenames... ]" +#define USAGE "s6-rc [ -v verbosity ] [ -n dryrunthrottle ] [ -t timeout ] [ -l live ] [ -b ] [ -u | -d ] [ -p ] [ -a ] help|list|listall|diff|change [ servicenames... ]" #define dieusage() strerr_dieusage(100, USAGE) typedef struct pidindex_s pidindex_t ; @@ -42,8 +43,6 @@ static unsigned int n ; static unsigned char *state ; static unsigned int *pendingdeps ; static tain_t deadline ; -static size_t prefixlen ; -static char *prefix ; static char dryrun[UINT_FMT] = "" ; static inline void announce (void) @@ -59,17 +58,49 @@ static inline void announce (void) strerr_diefu2sys(111, "write ", fn) ; } -static void print_services (void) +static int print_services (void) { unsigned int i = 0 ; for (; i < n ; i++) if (state[i] & 2) { - buffer_puts(buffer_1, db->string + db->services[i].name) ; - buffer_put(buffer_1, "\n", 1) ; + if (buffer_puts(buffer_1, db->string + db->services[i].name) < 0 + || buffer_put(buffer_1, "\n", 1) < 0) goto err ; } - if (!buffer_flush(buffer_1)) - strerr_diefu1sys(111, "write to stdout") ; + if (!buffer_flush(buffer_1)) goto err ; + return 0 ; + + err: + strerr_diefu1sys(111, "write to stdout") ; +} + +static int print_diff (void) +{ + s6_svstatus_t status ; + int e = 0 ; + unsigned int i = 0 ; + for (; i < db->nlong ; i++) + { + size_t namelen = strlen(db->string + db->services[i].name) ; + char fn[livelen + namelen + 14] ; + memcpy(fn, live, livelen) ; + memcpy(fn + livelen, "/servicedirs/", 13) ; + memcpy(fn + livelen + 13, db->string + db->services[i].name, namelen + 1) ; + if (!s6_svstatus_read(fn, &status)) + strerr_diefu2sys(111, "read longrun status for ", fn) ; + if ((state[i] & 1) != status.flagwantup) + { + e = 1 ; + if (buffer_put(buffer_1, status.flagwantup ? "+" : "-", 1) < 1 + || buffer_put(buffer_1, db->string + db->services[i].name, namelen) < 0 + || buffer_put(buffer_1, "\n", 1) < 1) goto err ; + } + } + if (!buffer_flush(buffer_1)) goto err ; + return e ; + + err: + strerr_diefu1sys(111, "write to stdout") ; } static uint32_t compute_timeout (unsigned int i, int h) @@ -92,9 +123,9 @@ static pid_t start_oneshot (unsigned int i, int h) char tfmt[UINT32_FMT] ; char vfmt[UINT_FMT] ; char ifmt[UINT_FMT] ; - char socketfn[livelen + S6RC_ONESHOT_RUNNER_LEN + 12] ; + char socketfn[livelen + S6RC_ONESHOT_RUNNER_LEN + 16] ; memcpy(socketfn, live, livelen) ; - memcpy(socketfn + livelen, "/scandir/" S6RC_ONESHOT_RUNNER "/s", 12 + S6RC_ONESHOT_RUNNER_LEN) ; + memcpy(socketfn + livelen, "/servicedirs/" S6RC_ONESHOT_RUNNER "/s", 16 + S6RC_ONESHOT_RUNNER_LEN) ; tfmt[uint32_fmt(tfmt, compute_timeout(i, h))] = 0 ; vfmt[uint_fmt(vfmt, verbosity)] = 0 ; ifmt[uint_fmt(ifmt, i)] = 0 ; @@ -132,15 +163,14 @@ static pid_t start_longrun (unsigned int i, int h) unsigned int m = 0 ; char fmt[UINT32_FMT] ; char vfmt[UINT_FMT] ; - char servicefn[livelen + prefixlen + svdlen + 26] ; + char servicefn[livelen + svdlen + 30] ; char const *newargv[7 + !!dryrun[0] * 6] ; memcpy(servicefn, live, livelen) ; - memcpy(servicefn + livelen, "/scandir/", 9) ; - memcpy(servicefn + livelen + 9, prefix, prefixlen) ; - memcpy(servicefn + livelen + 9 + prefixlen, db->string + db->services[i].name, svdlen) ; + memcpy(servicefn + livelen, "/servicedirs/", 13) ; + memcpy(servicefn + livelen + 13, db->string + db->services[i].name, svdlen) ; if (h) { - memcpy(servicefn + livelen + 9 + prefixlen + svdlen, "/notification-fd", 17) ; + memcpy(servicefn + livelen + 13 + svdlen, "/notification-fd", 17) ; if (access(servicefn, F_OK) < 0) { h = 2 ; @@ -148,7 +178,7 @@ static pid_t start_longrun (unsigned int i, int h) strerr_warnwu2sys("access ", servicefn) ; } } - servicefn[livelen + 9 + prefixlen + svdlen] = 0 ; + servicefn[livelen + 13 + svdlen] = 0 ; fmt[uint32_fmt(fmt, compute_timeout(i, !!h))] = 0 ; vfmt[uint_fmt(vfmt, verbosity)] = 0 ; if (dryrun[0]) @@ -175,12 +205,11 @@ static void success_longrun (unsigned int i, int h) if (!dryrun[0]) { size_t svdlen = strlen(db->string + db->services[i].name) ; - char fn[livelen + prefixlen + svdlen + 15] ; + char fn[livelen + svdlen + 19] ; memcpy(fn, live, livelen) ; - memcpy(fn + livelen, "/scandir/", 9) ; - memcpy(fn + livelen + 9, prefix, prefixlen) ; - memcpy(fn + livelen + 9 + prefixlen, db->string + db->services[i].name, svdlen) ; - memcpy(fn + livelen + 9 + prefixlen + svdlen, "/down", 6) ; + memcpy(fn + livelen, "/servicedirs/", 13) ; + memcpy(fn + livelen + 13, db->string + db->services[i].name, svdlen) ; + memcpy(fn + livelen + 13 + svdlen, "/down", 6) ; if (h) { if (unlink(fn) < 0 && verbosity) @@ -204,12 +233,11 @@ static void failure_longrun (unsigned int i, int h) if (h && !dryrun[0]) { size_t svdlen = strlen(db->string + db->services[i].name) ; - char fn[livelen + prefixlen + svdlen + 10] ; + char fn[livelen + svdlen + 14] ; char const *newargv[5] = { S6_EXTBINPREFIX "s6-svc", "-d", "--", fn, 0 } ; memcpy(fn, live, livelen) ; - memcpy(fn + livelen, "/scandir/", 9) ; - memcpy(fn + livelen + 9, prefix, prefixlen) ; - memcpy(fn + livelen + 9 + prefixlen, db->string + db->services[i].name, svdlen + 1) ; + memcpy(fn + livelen, "/servicedirs/", 13) ; + memcpy(fn + livelen + 13, db->string + db->services[i].name, svdlen + 1) ; if (!child_spawn0(newargv[0], newargv, (char const *const *)environ)) strerr_warnwu2sys("spawn ", newargv[0]) ; } @@ -286,12 +314,11 @@ static void on_failure (unsigned int i, int h, int crashed, unsigned int code) /* static inline void kill_oneshots (void) { - char fn[livelen + prefixlen + S6RC_ONESHOT_RUNNER_LEN + 10] ; + char fn[livelen + S6RC_ONESHOT_RUNNER_LEN + 14] ; char const *newargv[5] = { S6_EXTBINPREFIX "s6-svc", "-h", "--", fn, 0 } ; memcpy(fn, live, livelen) ; - memcpy(fn + livelen, "/scandir/", 9) ; - memcpy(fn + livelen + 9, prefix, prefixlen) ; - memcpy(fn + livelen + 9 + prefixlen, S6RC_ONESHOT_RUNNER, S6RC_ONESHOT_RUNNER_LEN + 1) ; + memcpy(fn + livelen, "/servicedirs/", 13) ; + memcpy(fn + livelen + 13, S6RC_ONESHOT_RUNNER, S6RC_ONESHOT_RUNNER_LEN + 1) ; if (!child_spawn0(newargv[0], newargv, (char const *const *)environ)) strerr_warnwu2sys("spawn ", newargv[0]) ; } @@ -397,11 +424,12 @@ static inline unsigned int lookup (char const *const *table, char const *command static inline unsigned int parse_command (char const *command) { - static char const *const command_table[5] = + static char const *const command_table[] = { "help", "list", "listall", + "diff", "change", 0 } ; @@ -416,6 +444,7 @@ static inline void print_help (void) "s6-rc help\n" "s6-rc [ -l live ] [ -a ] list [ servicenames... ]\n" "s6-rc [ -l live ] [ -a ] [ -u | -d ] listall [ servicenames... ]\n" +"s6-rc [ -l live ] diff\n" "s6-rc [ -l live ] [ -a ] [ -u | -d ] [ -p ] [ -v verbosity ] [ -t timeout ] [ -n dryrunthrottle ] change [ servicenames... ]\n" ; if (buffer_putsflush(buffer_1, help) < 0) strerr_diefu1sys(111, "write to stdout") ; @@ -482,7 +511,7 @@ int main (int argc, char const *const *argv) if (takelocks) { int livelock, compiledlock ; - if (!s6rc_lock(live, 1 + (what >= 3), &livelock, dbfn, 1, &compiledlock, blocking)) + if (!s6rc_lock(live, 1 + (what >= 4), &livelock, dbfn, 1, &compiledlock, blocking)) strerr_diefu1sys(111, "take locks") ; if (coe(livelock) < 0) strerr_diefu3sys(111, "coe ", live, "/lock") ; @@ -492,10 +521,8 @@ int main (int argc, char const *const *argv) } - /* Read the sizes of the suffix and compiled db */ + /* Read the size of the compiled db */ - if (!s6rc_livedir_prefixsize(live, &prefixlen)) - strerr_diefu2sys(111, "read prefix size for ", live) ; fdcompiled = open_readb(dbfn) ; if (!s6rc_db_read_sizes(fdcompiled, &dbblob)) strerr_diefu3sys(111, "read ", dbfn, "/n") ; @@ -511,23 +538,12 @@ int main (int argc, char const *const *argv) uint32_t depsblob[dbblob.ndeps << 1] ; char stringblob[dbblob.stringlen] ; unsigned char stateblob[n] ; - char prefixblob[prefixlen + 1] ; dbblob.services = serviceblob ; dbblob.argvs = argvblob ; dbblob.deps = depsblob ; dbblob.string = stringblob ; state = stateblob ; - prefix = prefixblob ; - - - /* Read the prefix */ - - { - ssize_t r = s6rc_livedir_prefix(live, prefix, prefixlen) ; - if (r != prefixlen) strerr_diefu2sys(111, "read prefix for ", live) ; - prefix[prefixlen] = 0 ; - } /* Read live state in bit 0 of state */ @@ -551,6 +567,11 @@ int main (int argc, char const *const *argv) } + /* s6-rc diff */ + + if (what == 3) return print_diff() ; + + /* Resolve the args and add them to the selection */ { @@ -606,8 +627,7 @@ int main (int argc, char const *const *argv) if (what == 1) { if (!up) invert_selection() ; - print_services() ; - return 0 ; + return print_services() ; } s6rc_graph_closure(db, state, 1, up) ; @@ -615,11 +635,7 @@ int main (int argc, char const *const *argv) /* Print the selection after closure */ - if (what == 2) - { - print_services() ; - return 0 ; - } + if (what == 2) return print_services() ; tain_now_g() ; tain_add_g(&deadline, &deadline) ; |