summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/s6-rc-compile.html5
-rw-r--r--doc/s6-rc.html11
-rw-r--r--src/include/s6-rc/s6rc-db.h2
-rw-r--r--src/s6-rc/s6-rc-compile.c23
-rw-r--r--src/s6-rc/s6-rc.c13
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>&nbsp;: up. </li>
<li> <tt>-d</tt>&nbsp;: down. </li>
+ <li> <tt>-D</tt>&nbsp;: 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 ;