diff options
-rw-r--r-- | doc/s6-rc-compile.html | 5 | ||||
-rw-r--r-- | doc/s6-rc.html | 11 | ||||
-rw-r--r-- | src/include/s6-rc/s6rc-db.h | 2 | ||||
-rw-r--r-- | src/s6-rc/s6-rc-compile.c | 23 | ||||
-rw-r--r-- | src/s6-rc/s6-rc.c | 13 |
5 files changed, 49 insertions, 5 deletions
diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html index d931b91..b429e8e 100644 --- a/doc/s6-rc-compile.html +++ b/doc/s6-rc-compile.html @@ -143,6 +143,11 @@ is ignored, but trailing whitespace is not. Lines starting with a <tt>#</tt> character are ignored. The file defines the <em>direct dependencies</em> of <em>service</em>, i.e. the services that must be up in order for <em>service</em> to work properly. </li> + <li> An optional regular file named <tt>flag-essential</tt>. The contents of this +file are irrelevant, only its presence is tested. If this file exists, the service +will be marked as essential, which means that a <tt>s6-rc -d change <em>foo</em></tt> +command will not stop the service. Only a <tt>s6-rc -D change <em>foo</em></tt> +command will. </li> </ul> <p> diff --git a/doc/s6-rc.html b/doc/s6-rc.html index 85a223e..bccc1b5 100644 --- a/doc/s6-rc.html +++ b/doc/s6-rc.html @@ -50,7 +50,7 @@ root privileges. 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> ] + s6-rc [ -l live ] [ -b ] [ -a ] [ -u | -d | -D ] [ -p ] [ -v <em>verbosity</em> ] [ -n <em>dryrunthrottle</em> ] [ -t timeout ] change [ <em>servicenames...</em> ] </pre> <ul> @@ -122,8 +122,17 @@ Default is <em>up</em>. <ul> <li> <tt>-u</tt> : up. </li> <li> <tt>-d</tt> : down. </li> + <li> <tt>-D</tt> : force down. </li> </ul> +<p> + The <tt>-d</tt> option is what should normally be used to down a set of services. +If a service is marked as <em>essential</em> (there is a <tt>flag-essential</tt> file +in its service definition directory), then s6-rc will refuse to stop that service. +The <tt>-D</tt> option will still force that service to shut down; that option should +only be used when the machine is going to be stopped. +</p> + <h3> <tt>s6-rc change</tt> control </h3> <ul> diff --git a/src/include/s6-rc/s6rc-db.h b/src/include/s6-rc/s6rc-db.h index c0d282d..0f03967 100644 --- a/src/include/s6-rc/s6rc-db.h +++ b/src/include/s6-rc/s6rc-db.h @@ -12,6 +12,8 @@ #define S6RC_DB_BANNER_END "\ns6rc-db: end\n" #define S6RC_DB_BANNER_END_LEN (sizeof(S6RC_DB_BANNER_END) - 1) +#define S6RC_DB_FLAG_ESSENTIAL 0x00000001U + typedef struct s6rc_oneshot_s s6rc_oneshot_t, *s6rc_oneshot_t_ref ; struct s6rc_oneshot_s diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c index 9ce6240..f2b6a84 100644 --- a/src/s6-rc/s6-rc-compile.c +++ b/src/s6-rc/s6-rc-compile.c @@ -351,10 +351,30 @@ static uint32_t read_timeout (int dfd, char const *srcdir, char const *name, cha return timeout ; } +static inline uint32_t read_flags (int dfd, char const *srcdir, char const *name) +{ + static char const *files[32] = + { + "flag-essential", + 0 + } ; + uint32_t flags = 0 ; + for (uint32_t i = 0 ; i < 32 ; i++) + { + if (!files[i]) break ; + if (access_at(dfd, files[i], F_OK, 0) < 0) + { + if (errno != ENOENT) + strerr_diefu6sys(111, "read ", srcdir, "/", name, "/", files[i]) ; + } + else flags |= i ; + } + return flags ; +} + static void add_common (before_t *be, int dfd, char const *srcdir, char const *name, common_t *common, servicetype_t svtype) { unsigned int dummy ; - common->annotation_flags = 0 ; add_name(be, srcdir, name, svtype, &dummy, &common->kname) ; if (!add_namelist(be, dfd, srcdir, name, "dependencies", &common->depindex, &common->ndeps)) { @@ -365,6 +385,7 @@ static void add_common (before_t *be, int dfd, char const *srcdir, char const *n } common->timeout[0] = read_timeout(dfd, srcdir, name, "timeout-down") ; common->timeout[1] = read_timeout(dfd, srcdir, name, "timeout-up") ; + common->annotation_flags = read_flags(dfd, srcdir, name) ; } static inline void add_oneshot (before_t *be, int dfd, char const *srcdir, char const *name) diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c index 76e38da..455bf16 100644 --- a/src/s6-rc/s6-rc.c +++ b/src/s6-rc/s6-rc.c @@ -26,7 +26,7 @@ #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|diff|change [ servicenames... ]" +#define USAGE "s6-rc [ -v verbosity ] [ -n dryrunthrottle ] [ -t timeout ] [ -l live ] [ -b ] [ -u | -d | -D ] [ -p ] [ -a ] help|list|listall|diff|change [ servicenames... ]" #define dieusage() strerr_dieusage(100, USAGE) typedef struct pidindex_s pidindex_t ; @@ -47,6 +47,7 @@ static unsigned char *state ; static unsigned int *pendingdeps ; static tain_t deadline ; static int lameduck = 0 ; +static int forcestop = 0 ; static char dryrun[UINT_FMT] = "" ; static inline void announce (void) @@ -261,6 +262,11 @@ static void examine (unsigned int i, int h) strerr_warni4x("service ", name, ": already ", h ? "up" : "down") ; broadcast_success(i, h) ; } + else if (!h && !forcestop && db->services[i].flags & S6RC_DB_FLAG_ESSENTIAL) + { + if (verbosity) + strerr_warnw3x("service ", name, " is marked as essential, not stopping it") ; + } else { pidindex[npids].pid = i < db->nlong ? start_longrun(i, h) : start_oneshot(i, h) ; @@ -450,7 +456,7 @@ static inline void print_help (void) "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" ; +"s6-rc [ -l live ] [ -a ] [ -u | -d | -D ] [ -p ] [ -v verbosity ] [ -t timeout ] [ -n dryrunthrottle ] change [ servicenames... ]\n" ; if (buffer_putsflush(buffer_1, help) < 0) strerr_diefu1sys(111, "write to stdout") ; } @@ -465,7 +471,7 @@ int main (int argc, char const *const *argv) subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "v:n:t:l:udpaXb", &l) ; + int opt = subgetopt_r(argc, argv, "v:n:t:l:uDdpaXb", &l) ; if (opt == -1) break ; switch (opt) { @@ -480,6 +486,7 @@ int main (int argc, char const *const *argv) case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; case 'l' : live = l.arg ; break ; case 'u' : up = 1 ; break ; + case 'D' : forcestop = 1 ; case 'd' : up = 0 ; break ; case 'p' : prune = 1 ; break ; case 'a' : selectlive = 1 ; break ; |