aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-06-09 05:27:48 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-06-09 05:27:48 +0000
commit958958d74337a6ddaf649968d188e768984100e0 (patch)
tree7f32dfc1bea9c4d010a344e130707e638620a0fc
parent241d2079a25d77e090beb0b767984928dbbc8cd6 (diff)
downloads6-rc-958958d74337a6ddaf649968d188e768984100e0.tar.gz
Prepare for 0.6.2.0; implement s6-rc reload
Also support reload-signal in the service definition directory.
-rw-r--r--INSTALL2
-rw-r--r--NEWS5
-rw-r--r--doc/index.html6
-rw-r--r--doc/s6-rc-oneshot-run.html4
-rw-r--r--doc/s6-rc.html21
-rw-r--r--doc/upgrade.html3
-rw-r--r--package/deps-build2
-rw-r--r--package/info2
-rw-r--r--src/libs6rc/s6rc_servicedir_internal.c1
-rw-r--r--src/s6-rc/s6-rc-oneshot-run.c7
-rw-r--r--src/s6-rc/s6-rc.c66
11 files changed, 97 insertions, 22 deletions
diff --git a/INSTALL b/INSTALL
index 90b918f..35c5307 100644
--- a/INSTALL
+++ b/INSTALL
@@ -8,7 +8,7 @@ Build Instructions
- GNU make version 3.81 or later
- skalibs version 2.15.0.1 or later: https://skarnet.org/software/skalibs/
- execline version 2.9.9.2 or later: https://skarnet.org/software/execline/
- - s6 version 2.15.0.1 or later: https://skarnet.org/software/s6/
+ - s6 version 2.15.1.0 or later: https://skarnet.org/software/s6/
This software will run on any operating system that implements
POSIX.1-2024, available at:
diff --git a/NEWS b/NEWS
index 024e549..9a4a32f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,11 @@
Changelog for s6-rc.
-In 0.6.1.2
+In 0.6.2.0
----------
- Bugfixes.
- - s6-rc-init is now idempotent and behaves better in pathological situations
+ - s6-rc-init is now idempotent and behaves better in pathological situations.
+ - New "s6-rc reload" command.
In 0.6.1.1
diff --git a/doc/index.html b/doc/index.html
index ed486bf..426bdb5 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -55,7 +55,7 @@ requirement if you link against the shared version of the skalibs library. </li>
<li> <a href="//skarnet.org/software/execline/">execline</a> version
2.9.9.2 or later. It's a build-time <em>and</em> run-time requirement. </li>
<li> <a href="//skarnet.org/software/s6/">s6</a> version
-2.15.0.1 or later. It's a build-time <em>and</em> run-time requirement. </li>
+2.15.1.0 or later. It's a build-time <em>and</em> run-time requirement. </li>
</ul>
<h3> Licensing </h3>
@@ -69,8 +69,8 @@ requirement if you link against the shared version of the skalibs library. </li>
<ul>
<li> The current released version of s6-rc is
-<a href="s6-rc-0.6.1.2.tar.gz">0.6.1.2</a>.
-You can access its checksum <a href="s6-rc-0.6.1.2.tar.gz.sha256">here</a>. </li>
+<a href="s6-rc-0.6.2.0.tar.gz">0.6.2.0</a>.
+You can access its checksum <a href="s6-rc-0.6.2.0.tar.gz.sha256">here</a>. </li>
<li> Alternatively, you can checkout a copy of the
<a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-rc/">s6-rc
git repository</a>:
diff --git a/doc/s6-rc-oneshot-run.html b/doc/s6-rc-oneshot-run.html
index ee454ae..15f10aa 100644
--- a/doc/s6-rc-oneshot-run.html
+++ b/doc/s6-rc-oneshot-run.html
@@ -34,7 +34,7 @@ in internal scripts created by
<h2 id="interface"> Interface </h2>
<pre>
- s6-rc-oneshot-run [ -l <em>live</em> ] [ -b ] up|down <em>n</em>
+ s6-rc-oneshot-run [ -l <em>live</em> ] [ -b ] up|down|reload <em>n</em>
</pre>
<ul>
@@ -44,6 +44,8 @@ in the current compiled service database (i.e. the compiled linked from the
live directory). </li>
<li> <tt>up</tt> or <tt>down</tt> are run with the <tt>RC_NAME</tt>
environment variable set to the name of the service. </li>
+ <li> A <tt>reload</tt> command causes the <tt>up</tt> script to be run, with
+an additional <tt>RC_RELOAD</tt> environment variable containing 1. </li>
</ul>
<h2 id="options"> Options </h2>
diff --git a/doc/s6-rc.html b/doc/s6-rc.html
index a7eb9d9..bb16113 100644
--- a/doc/s6-rc.html
+++ b/doc/s6-rc.html
@@ -244,6 +244,27 @@ below. It will run the engine to start a set of services.
below. It will run the engine to stop a set of services.
</p>
+<h3> s6-rc reload </h3>
+
+<p>
+ <tt>s6-rc reload</tt> sends a "reload" command to the list of services
+given on the command line, which must all be up. For a longrun,
+<tt>s6-rc reload</tt> sends an <a href="//skarnet.org/software/s6/s6-svc.html">s6-svc -l</a>
+command to the service, which causes it to receive a SIGHUP, or any
+overriding signal configured in the <tt>reload-signal</tt> file.
+For a oneshot, the service's <tt>up</tt> script is executed, with
+an additional <tt>RC_RELOAD</tt> environment variable containing 1.
+</p>
+
+<p>
+ <tt>s6-rc reload</tt> is special in that it does not use the live state
+at all (except to verify that the services the user wants to reload are
+indeed up) and does not involve the dependency engine. It only operates on
+the services given as arguments on the command line. It is implemented at
+the s6-rc level because it is sometimes useful to ask for a <em>oneshot</em>
+to be reloaded.
+</p>
+
<h3> s6-rc change </h3>
<p>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index d63dc34..0aac5cf 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -31,7 +31,7 @@ minor and bugfix version changes.
<h1> What has changed in s6-rc </h1>
-<h2> in 0.6.1.2 </h2>
+<h2> in 0.6.2.0 </h2>
<ul>
<li> <a href="//skarnet.org/software/skalibs/">skalibs</a>
@@ -40,6 +40,7 @@ dependency bumped to 2.15.0.1. </li>
dependency bumped to 2.9.9.2. </li>
<li> <a href="//skarnet.org/software/s6/">s6</a>
dependency bumped to 2.15.0.1. </li>
+ <li> New <a href="s6-rc.html">s6-rc reload</a> command. </li>
</ul>
<h2> in 0.6.1.1 </h2>
diff --git a/package/deps-build b/package/deps-build
index 842d3a2..c270804 100644
--- a/package/deps-build
+++ b/package/deps-build
@@ -1,3 +1,3 @@
true true /package/prog/skalibs 2.15.0.1 libskarnet
true false /package/admin/execline 2.9.9.2 libexecline
-true true /package/admin/s6 2.15.0.1 libs6
+true true /package/admin/s6 2.15.1.0 libs6
diff --git a/package/info b/package/info
index bc728bb..0b55290 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
package=s6-rc
-version=0.6.1.2
+version=0.6.2.0
category=admin
package_macro_name=S6RC
diff --git a/src/libs6rc/s6rc_servicedir_internal.c b/src/libs6rc/s6rc_servicedir_internal.c
index 419fd88..e81f378 100644
--- a/src/libs6rc/s6rc_servicedir_internal.c
+++ b/src/libs6rc/s6rc_servicedir_internal.c
@@ -25,6 +25,7 @@ static s6_servicedir_desc const svdir_file_list[] =
{ .name = "timeout-finish", .type = S6_FILETYPE_UINT, .options = 0 },
{ .name = "max-death-tally", .type = S6_FILETYPE_UINT, .options = 0 },
{ .name = "down-signal", .type = S6_FILETYPE_NORMAL, .options = 0 },
+ { .name = "reload-signal", .type = S6_FILETYPE_NORMAL, .options = 0 },
{ .name = "flag-newpidns", .type = S6_FILETYPE_EMPTY, .options = 0 },
{ .name = "template", .type = S6_FILETYPE_DIR, .options = 0 },
{ .name = "data", .type = S6_FILETYPE_DIR, .options = 0 },
diff --git a/src/s6-rc/s6-rc-oneshot-run.c b/src/s6-rc/s6-rc-oneshot-run.c
index dbaa38d..dc7bf06 100644
--- a/src/s6-rc/s6-rc-oneshot-run.c
+++ b/src/s6-rc/s6-rc-oneshot-run.c
@@ -21,6 +21,7 @@ enum golb_e
{
GOLB_UP = 0x01,
GOLB_BLOCK = 0x02,
+ GOLB_RELOAD = 0x04,
} ;
enum gola_e
@@ -51,6 +52,7 @@ int main (int argc, char const *const *argv)
if (!strcasecmp(argv[0], "up")) wgolb |= GOLB_UP ;
else if (!strcasecmp(argv[0], "down")) wgolb &= ~GOLB_UP ;
+ else if (!strcasecmp(argv[0], "reload")) wgolb |= GOLB_UP | GOLB_RELOAD ;
else dieusage() ;
if (!uint0_scan(argv[1], &number)) dieusage() ;
@@ -112,12 +114,13 @@ int main (int argc, char const *const *argv)
char const *const *sargv = db.argvs + sv->x.oneshot.argv[!!(wgolb & GOLB_UP)] ;
char const *newargv[sargc + 1] ;
char const **p = newargv ;
- char modif[namelen + 9] ;
+ char modif[namelen + 21] ;
memcpy(modif, "RC_NAME=", 8) ;
memcpy(modif + 8, db.string + sv->name, namelen + 1) ;
+ if (wgolb & GOLB_RELOAD) memcpy(modif + 9 + namelen, "RC_RELOAD=1", 12) ;
while (sargc--) *p++ = *sargv++ ;
*p = 0 ;
- xmexec0_n(newargv, modif, namelen + 9, 1) ;
+ xmexec0_n(newargv, modif, namelen + (wgolb & GOLB_RELOAD ? 21 : 9), 1 + !!(wgolb & GOLB_RELOAD)) ;
}
}
}
diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c
index 74d48c5..b74b902 100644
--- a/src/s6-rc/s6-rc.c
+++ b/src/s6-rc/s6-rc.c
@@ -38,6 +38,7 @@ enum what_e
WHAT_CHANGE,
WHAT_START,
WHAT_STOP,
+ WHAT_RELOAD,
} ;
struct what_s
@@ -182,7 +183,7 @@ static inline pid_t start_oneshot (unsigned int i, int h)
newargv[m++] = tfmt ;
newargv[m++] = "--" ;
newargv[m++] = socketfn ;
- newargv[m++] = h ? "up" : "down" ;
+ newargv[m++] = h == 3 ? "reload" : h ? "up" : "down" ;
newargv[m++] = ifmt ;
if (dryrun[0])
{
@@ -227,7 +228,7 @@ static inline pid_t start_longrun (unsigned int i, int h)
newargv[m++] = "--" ;
}
newargv[m++] = S6_EXTBINPREFIX "s6-svc" ;
- newargv[m++] = h ? h == 2 ? "-uwu" : "-uwU" : "-dwD" ;
+ newargv[m++] = h == 3 ? "-l" : h ? h == 2 ? "-uwu" : "-uwU" : "-dwD" ;
newargv[m++] = "-T" ;
newargv[m++] = fmt ;
newargv[m++] = "--" ;
@@ -266,7 +267,7 @@ static inline void success_longrun (unsigned int i, int h)
static inline void failure_longrun (unsigned int i, int h)
{
- if (h && !dryrun[0])
+ if (!dryrun[0])
{
size_t svdlen = strlen(db->string + db->services[i].name) ;
char fn[livelen + svdlen + 14] ;
@@ -333,22 +334,25 @@ static void broadcast_success (unsigned int i, int h)
static inline void on_success (unsigned int i, int h)
{
- if (i < db->nlong) success_longrun(i, h) ;
- if (h) state[i] |= 1 ; else state[i] &= 254 ;
- announce() ;
+ if (h != 3)
+ {
+ if (i < db->nlong) success_longrun(i, h) ;
+ if (h) state[i] |= 1 ; else state[i] &= 254 ;
+ announce() ;
+ }
if (verbosity >= 2)
- strerr_warni5x(dryrun[0] ? "dry run: " : "", "service ", db->string + db->services[i].name, " successfully st", h ? "arted" : "opped") ;
- if (!lameduck) broadcast_success(i, h) ;
+ strerr_warni5x(dryrun[0] ? "dry run: " : "", "service ", db->string + db->services[i].name, " successfully ", h == 3 ? "reloaded" : h ? "started" : "stopped") ;
+ if (!lameduck && h != 3) broadcast_success(i, h) ;
}
static inline void on_failure (unsigned int i, int h, int crashed, unsigned int code)
{
- if (i < db->nlong) failure_longrun(i, h) ;
+ if (h != 3 && i < db->nlong) failure_longrun(i, h) ;
if (verbosity)
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, code)] = 0 ;
- strerr_warnwu7x(dryrun[0] ? "(dry run) " : "", h ? "start" : "stop", " service ", db->string + db->services[i].name, ": command ", crashed ? "crashed with signal " : "exited ", fmt) ;
+ strerr_warnwu7x(dryrun[0] ? "(dry run) " : "", h == 3 ? "reload" : h ? "start" : "stop", " service ", db->string + db->services[i].name, ": command ", crashed ? "crashed with signal " : "exited ", fmt) ;
}
}
@@ -457,6 +461,38 @@ static void invert_selection (void)
while (i--) state[i] ^= 2 ;
}
+static int reload (void)
+{
+ iopause_fd x = { .fd = selfpipe_fd(), .events = IOPAUSE_READ } ;
+ int exitcode = 0 ;
+ unsigned int i = n ;
+ pidindex_t pidindexblob[n] ;
+ pidindex = pidindexblob ;
+
+ while (i--) if (state[i] & 2)
+ {
+ pid_t pid ;
+ if (!(state[i] & 1))
+ {
+ if (verbosity) strerr_warnw("service ", db->string + db->services[i].name, " is down - not reloading") ;
+ continue ;
+ }
+ pid = i < db->nlong ? start_longrun(i, 3) : start_oneshot(i, 3) ;
+ if (!pid) strerr_diefusys(111, "send reload command to service ", db->string + db->services[i].name) ;
+ pidindex[npids].pid = pid ;
+ pidindex[npids++].i = i ;
+ }
+
+ while (npids)
+ {
+ int r = iopause_g(&x, 1, &deadline) ;
+ if (r < 0) strerr_diefu1sys(111, "iopause") ;
+ if (!r) strerr_dief(2, "timed out") ;
+ if (!handle_signals(3)) exitcode = 1 ;
+ }
+ return exitcode ;
+}
+
static inline enum what_e parse_command (char const *command)
{
static struct what_s const command_table[] =
@@ -466,6 +502,7 @@ static inline enum what_e parse_command (char const *command)
{ .s = "help", .e = WHAT_HELP },
{ .s = "list", .e = WHAT_LIST },
{ .s = "listall", .e = WHAT_LISTALL },
+ { .s = "reload", .e = WHAT_RELOAD },
{ .s = "start", .e = WHAT_START },
{ .s = "stop", .e = WHAT_STOP },
} ;
@@ -660,6 +697,15 @@ int main (int argc, char const *const *argv)
close(fdcompiled) ;
+ /* s6-rc reload */
+
+ if (what == WHAT_RELOAD)
+ {
+ if (!argc) strerr_dief(100, "reload: too few arguments") ;
+ _exit(reload()) ;
+ }
+
+
/* Add live state to selection */
if (wgolb & GOLB_SELECTLIVE)