aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-10-05 18:03:35 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-10-05 18:03:35 +0000
commitf706ab3b309a4c9a0425ac23d5ffff7ead48fcb2 (patch)
tree741b3d5367b083a53b9cde74d6a6427eb310f307
parent9f4ba23454acf1d3925ffb7ea2123c9b19c2bf24 (diff)
downloads6-rc-f706ab3b309a4c9a0425ac23d5ffff7ead48fcb2.tar.gz
Add -L catchall to s6-rc-compile and s6-rc-fdholder-filler
-rw-r--r--NEWS3
-rw-r--r--doc/s6-rc-compile.html7
-rw-r--r--doc/s6-rc-fdholder-filler.html4
-rw-r--r--src/s6-rc/s6-rc-compile.c25
-rw-r--r--src/s6-rc/s6-rc-fdholder-filler.c142
5 files changed, 123 insertions, 58 deletions
diff --git a/NEWS b/NEWS
index cb0fec6..d5c8630 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,8 @@ In 0.7.1.0
----------
- Bugfixes.
- - Databases now embed the major version they were built with
+ - Databases now embed the major version they were built with.
+ - New -L option to s6-rc-compile. (and s6-rc-fdholder-filler)
In 0.7.0.0
diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html
index fc4a9c6..09e71d6 100644
--- a/doc/s6-rc-compile.html
+++ b/doc/s6-rc-compile.html
@@ -37,7 +37,7 @@ the current service database via
<h2> Interface </h2>
<pre>
- s6-rc-compile [ -v <em>verbosity</em> ] [ -h <em>fdhuser</em> ] [ -b ] <em>compiled</em> <em>source...</em>
+ s6-rc-compile [ -v <em>verbosity</em> ] [ -h <em>fdhuser</em> ] [ -L <em>catchall</em> ] [ -b ] <em>compiled</em> <em>source...</em>
</pre>
<ul>
@@ -70,6 +70,11 @@ what s6-rc-compile is doing. 3 or more is heavy debug output. </li>
program, which maintains the pipes for the longrun pipelines, to run
as user <em>fdhuser</em>. By default, it runs as the user owning
the supervision tree, i.e. most likely <tt>root</tt>. </li>
+ <li> <tt>-L&nbsp;<em>catchall</em></tt>&nbsp;: assume that a catch-all
+logger service will be running on <em>catchall</em> and ensure that its
+fifo is properly held in the fdholder (which avoids services getting killed
+by SIGPIPE if they're writing uncaught logs while the catch-all logger is
+restarting). </li>
<li> <tt>-b</tt>&nbsp;: make
<a href="s6-rc-oneshot-run.html">s6-rc-oneshot-run</a>
invocations wait instead of fail on lock contention. This
diff --git a/doc/s6-rc-fdholder-filler.html b/doc/s6-rc-fdholder-filler.html
index 5f47ec4..b160573 100644
--- a/doc/s6-rc-fdholder-filler.html
+++ b/doc/s6-rc-fdholder-filler.html
@@ -35,7 +35,7 @@ in internal scripts created by
<h2> Interface </h2>
<pre>
- s6-rc-fdholder-filler [ -1 ] [ -t <em>timeout</em> ] &lt; <em>longrunnamesfile</em>
+ s6-rc-fdholder-filler [ -1 ] [ -t <em>timeout</em> ] [ -L <em>catchall</em> ] &lt; <em>longrunnamesfile</em>
</pre>
<ul>
@@ -63,6 +63,8 @@ successful operation. This is used as a notification mechanism. </li>
<li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if the operation cannot be
achieved in <em>timeout</em> milliseconds, abort and report failure. By
default, <em>timeout</em> is 0, meaning infinite. </li>
+ <li> <tt>-L&nbsp;<em>catchall</em></tt>&nbsp;: also store the fifo for
+the catch-all logger whose service directory is <em>catchall</em>. </li>
</ul>
<h2> Exit codes </h2>
diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c
index 83e751c..0bfe4d7 100644
--- a/src/s6-rc/s6-rc-compile.c
+++ b/src/s6-rc/s6-rc-compile.c
@@ -21,7 +21,7 @@
#include <s6-rc/config.h>
#include <s6-rc/s6rc.h>
-#define USAGE "s6-rc-compile [ -v verbosity ] [ -h fdholder_user ] [ -b ] destdir sources..."
+#define USAGE "s6-rc-compile [ -v verbosity ] [ -h fdholder-user ] [ -L catchall-logger ] [ -b ] destdir sources..."
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_dief(111, "out of memory") ;
@@ -36,6 +36,7 @@ enum gola_e
{
GOLA_VERBOSITY,
GOLA_FDHUSER,
+ GOLA_CATCHALL,
GOLA_N
} ;
@@ -1122,7 +1123,7 @@ static inline void write_oneshot_runner (char const *compiled, int blocking)
auto_rights(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", 0755) ;
}
-static inline void write_fdholder (char const *compiled, s6rc_db_t const *db, char const *fdhuser)
+static inline void write_fdholder (char const *compiled, s6rc_db_t const *db, char const *fdhuser, char const *catchall)
{
unsigned int nfds = 0 ;
size_t base = satmp.len ;
@@ -1163,7 +1164,14 @@ static inline void write_fdholder (char const *compiled, s6rc_db_t const *db, ch
EXECLINE_EXTBINPREFIX "if -nt --\n {\n "
EXECLINE_EXTBINPREFIX "redirfd -r 0 ./data/autofilled\n "
S6_EXTBINPREFIX "s6-ipcclient -l0 -- s\n "
- S6RC_EXTLIBEXECPREFIX "s6-rc-fdholder-filler -1 --\n }\n "
+ S6RC_EXTLIBEXECPREFIX "s6-rc-fdholder-filler -1 ")) goto err ;
+ if (catchall)
+ {
+ if (!stralloc_cats(&satmp, "-L ")
+ || !string_quote(&satmp, catchall, strlen(catchall))
+ || !stralloc_catb(&satmp, " ", 1)) goto err ;
+ }
+ if (!stralloc_cats(&satmp, "--\n }\n "
S6_EXTBINPREFIX "s6-svc -t .\n}\n")) goto err ;
if (fdhuser)
{
@@ -1619,6 +1627,7 @@ static inline void write_compiled (
unsigned int nbundles,
uint32_t const *bdeps,
char const *fdhuser,
+ char const *catchall,
int blocking)
{
if (verbosity >= 2) strerr_warni("writing compiled information to ", compiled) ;
@@ -1629,7 +1638,7 @@ static inline void write_compiled (
stralloc_free(&data) ;
write_db(compiled, db) ;
write_oneshot_runner(compiled, blocking) ;
- write_fdholder(compiled, db, fdhuser) ;
+ write_fdholder(compiled, db, fdhuser, catchall) ;
write_servicedirs(compiled, db, srcdirs) ;
}
@@ -1643,6 +1652,7 @@ int main (int argc, char const *const *argv)
{
{ .so = 'v', .lo = "verbosity", .i = GOLA_VERBOSITY },
{ .so = 'h', .lo = "fdholder-user", .i = GOLA_FDHUSER },
+ { .so = 'L', .lo = "catchall-logger", .i = GOLA_CATCHALL },
} ;
before_t before = BEFORE_ZERO ;
uint64_t wgolb = 0 ;
@@ -1659,6 +1669,11 @@ int main (int argc, char const *const *argv)
if (!uint0_scan(wgola[GOLA_VERBOSITY], &verbosity))
strerr_dief(100, "verbosity must be an unsigned integer") ;
}
+ if (wgola[GOLA_CATCHALL])
+ {
+ if (wgola[GOLA_CATCHALL][0] != '/')
+ strerr_dief(100, "catchall-logger must be an absolute path") ;
+ }
compiled = *argv++ ;
before.specialdeps[0] = add_internal_longrun(&before, S6RC_ONESHOT_RUNNER) ;
@@ -1707,7 +1722,7 @@ int main (int argc, char const *const *argv)
db.deps = deps ;
flatlist_services(&db, sarray) ;
propagate_bundle_flags(&db, bundles, nbundles, bdeps) ;
- write_compiled(compiled, &db, srcdirs, bundles, nbundles, bdeps, wgola[GOLA_FDHUSER], wgolb & GOLB_BLOCK) ;
+ write_compiled(compiled, &db, srcdirs, bundles, nbundles, bdeps, wgola[GOLA_FDHUSER], wgola[GOLA_CATCHALL], wgolb & GOLB_BLOCK) ;
}
}
diff --git a/src/s6-rc/s6-rc-fdholder-filler.c b/src/s6-rc/s6-rc-fdholder-filler.c
index a64a7f1..37d1945 100644
--- a/src/s6-rc/s6-rc-fdholder-filler.c
+++ b/src/s6-rc/s6-rc-fdholder-filler.c
@@ -6,20 +6,36 @@
#include <errno.h>
#include <skalibs/types.h>
-#include <skalibs/sgetopt.h>
+#include <skalibs/gol.h>
+#include <skalibs/prog.h>
#include <skalibs/strerr.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/tai.h>
#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
#include <s6/fdholder.h>
-#define USAGE "s6-rc-fdholder-filler [ -1 ] [ -t timeout ] < autofilled-filename"
+#include <s6-rc/config.h>
+
+#define USAGE "s6-rc-fdholder-filler [ -1 ] [ -t timeout ] [ -L catchall-logger ] < autofilled-filename"
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "stralloc_catb")
+enum golb_e
+{
+ GOLB_1 = 0x1,
+} ;
+
+enum gola_e
+{
+ GOLA_TIMEOUT,
+ GOLA_CATCHALL,
+ GOLA_N,
+} ;
+
static inline uint8_t cclass (char c)
{
switch (c)
@@ -64,71 +80,97 @@ static inline void parse_servicenames (stralloc *sa, genalloc *g)
int main (int argc, char const *const *argv)
{
+ static gol_bool const rgolb[1] =
+ {
+ { .so = '1', .lo = "notify-stdout", .clear = 0, .set = GOLB_1 },
+ } ;
+ static gol_arg const rgola[GOLA_N] =
+ {
+ { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT },
+ { .so = 'L', .lo = "catchall-logger", .i = GOLA_CATCHALL },
+ } ;
s6_fdholder_t a = S6_FDHOLDER_ZERO ;
stralloc sa = STRALLOC_ZERO ;
genalloc ga = GENALLOC_ZERO ; /* size_t */
size_t n ;
size_t const *indices ;
- tain deadline ;
- int notif = 0 ;
+ tain deadline = TAIN_INFINITE_RELATIVE ;
+ uint64_t wgolb = 0 ;
+ char const *wgola[GOLA_N] = { 0 } ;
+ tain offset = { .sec = TAI_ZERO } ;
+ int p[2] ;
+ size_t m = 0 ;
PROG = "s6-rc-fdholder-filler" ;
+
+ {
+ unsigned int golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ;
+ argc -= golc ; argv += golc ;
+ }
+ if (wgola[GOLA_TIMEOUT])
{
unsigned int t = 0 ;
- subgetopt l = SUBGETOPT_ZERO ;
- for (;;)
- {
- int opt = subgetopt_r(argc, argv, "1t:", &l) ;
- if (opt == -1) break ;
- switch (opt)
- {
- case '1': notif = 1 ; break ;
- case 't': if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
+ if (!uint0_scan(wgola[GOLA_TIMEOUT], &t))
+ strerr_dief(100, "timeout must be an unsigned integer") ;
if (t) tain_from_millisecs(&deadline, t) ;
- else deadline = tain_infinite_relative ;
+ }
+ if (wgola[GOLA_CATCHALL])
+ {
+ if (wgola[GOLA_CATCHALL][0] != '/')
+ strerr_dief(100, "catchall-logger must be an absolute path") ;
}
parse_servicenames(&sa, &ga) ;
n = genalloc_len(size_t, &ga) ;
indices = genalloc_s(size_t, &ga) ;
- if (n)
+
+ s6_fdholder_fd_t dump[1 + (n<<1)] ;
+
+ close(0) ;
+ s6_fdholder_init(&a, 6) ;
+ tain_now_set_stopwatch_g() ;
+ tain_add_g(&deadline, &deadline) ;
+
+ if (wgola[GOLA_CATCHALL])
{
- tain offset = { .sec = TAI_ZERO } ;
- int p[2] ;
- size_t i = 0 ;
- s6_fdholder_fd_t dump[n<<1] ;
- close(0) ;
- s6_fdholder_init(&a, 6) ;
- tain_now_set_stopwatch_g() ;
- tain_add_g(&deadline, &deadline) ;
- for (; i < n ; i++)
+ size_t len = strlen(wgola[GOLA_CATCHALL]) ;
+ char fn[len + 6] ;
+ memcpy(fn, wgola[GOLA_CATCHALL], len) ;
+ memcpy(fn + len, "/fifo", 6) ;
+ dump[m].fd = open_read(fn) ;
+ if (dump[m].fd >= 0)
{
- size_t len = strlen(sa.s + indices[i]) ;
- if (len + 12 > S6_FDHOLDER_ID_SIZE)
- {
- errno = ENAMETOOLONG ;
- strerr_diefu2sys(111, "create identifier for ", sa.s + indices[i]) ;
- }
- if (pipe(p) < 0)
- strerr_diefu1sys(111, "create pipe") ;
- dump[i<<1].fd = p[0] ;
- tain_add_g(&dump[i<<1].limit, &tain_infinite_relative) ;
- offset.nano = i << 1 ;
- tain_add(&dump[i<<1].limit, &dump[i<<1].limit, &offset) ;
- memcpy(dump[i<<1].id, "pipe:s6rc-r-", 12) ;
- memcpy(dump[i<<1].id + 12, sa.s + indices[i], len + 1) ;
- dump[(i<<1)+1].fd = p[1] ;
- offset.nano = 1 ;
- tain_add(&dump[(i<<1)+1].limit, &dump[i<<1].limit, &offset) ;
- memcpy(dump[(i<<1)+1].id, dump[i<<1].id, 13 + len) ;
- dump[(i<<1)+1].id[10] = 'w' ;
+ tain_add_g(&dump[m].limit, &tain_infinite_relative) ;
+ memcpy(dump[m].id, "pipe:s6-rc-r/s6-svscan-log", 27) ;
+ m++ ;
}
- if (!s6_fdholder_setdump_g(&a, dump, n << 1, &deadline))
- strerr_diefu1sys(111, "transfer pipes") ;
}
- if (notif) write(1, "\n", 1) ;
+ for (size_t i = 0 ; i < n ; i++)
+ {
+ size_t len = strlen(sa.s + indices[i]) ;
+ if (len + 12 > S6_FDHOLDER_ID_SIZE)
+ {
+ errno = ENAMETOOLONG ;
+ strerr_diefusys(111, "create identifier for ", sa.s + indices[i]) ;
+ }
+ if (pipe(p) == -1) strerr_diefu1sys(111, "create pipe") ;
+ dump[m].fd = p[0] ;
+ tain_add_g(&dump[m].limit, &tain_infinite_relative) ;
+ offset.nano = m ;
+ tain_add(&dump[m].limit, &dump[m].limit, &offset) ;
+ memcpy(dump[m].id, "pipe:s6rc-r-", 12) ;
+ memcpy(dump[m].id + 12, sa.s + indices[i], len + 1) ;
+ m++ ;
+ dump[m].fd = p[1] ;
+ offset.nano = 1 ;
+ tain_add(&dump[m].limit, &dump[m-1].limit, &offset) ;
+ memcpy(dump[m].id, dump[m-1].id, 13 + len) ;
+ dump[m].id[10] = 'w' ;
+ m++ ;
+ }
+
+ if (!s6_fdholder_setdump_g(&a, dump, m, &deadline))
+ strerr_diefusys(111, "transfer pipes") ;
+
+ if (wgolb & GOLB_1) write(1, "\n", 1) ;
return 0 ;
}