aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2025-11-10 03:58:19 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2025-11-10 03:58:19 +0000
commit8c7a6fdf4b9cae2d44a9ab03e0c4df5c2f59eb9b (patch)
tree472cca7707a6b60e81e6c8c33a406926e860d251
parente8f96316e667e4366b0b452d97874861a56050fd (diff)
downloads6-frontend-8c7a6fdf4b9cae2d44a9ab03e0c4df5c2f59eb9b.tar.gz
Refactor and implement live_restart
-rw-r--r--src/s6-frontend/live_startstop.c152
-rw-r--r--src/s6-frontend/s6-frontend-internal.h2
2 files changed, 94 insertions, 60 deletions
diff --git a/src/s6-frontend/live_startstop.c b/src/s6-frontend/live_startstop.c
index bbe72c9..e1d795b 100644
--- a/src/s6-frontend/live_startstop.c
+++ b/src/s6-frontend/live_startstop.c
@@ -29,7 +29,7 @@ enum gola_e
GOLA_N
} ;
-int live_startstop (char const *const *argv, int h)
+static unsigned int parse_options (char const *const *argv, uint64_t *wgolb, unsigned int *timeout)
{
static gol_bool const rgolb[] =
{
@@ -39,25 +39,75 @@ int live_startstop (char const *const *argv, int h)
{
{ .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT },
} ;
-
char const *wgola[GOLA_N] = { 0 } ;
- uint64_t wgolb = 0 ;
- unsigned int t = 0 ;
- size_t argc = env_len(argv) ;
+ unsigned int argc = GOL_argv(argv, rgolb, rgola, wgolb, wgola) ;
+ if (wgola[GOLA_TIMEOUT])
+ {
+ if (!uint0_scan(wgola[GOLA_TIMEOUT], timeout))
+ strerr_dief1x(100, "timeout must be an integer (milliseconds)") ;
+ }
+ return argc ;
+}
+
+static int run_s6rc_change (char const *const *services, unsigned int n, int h, int dryrun, unsigned int timeout, unsigned int nstate, char const *dbfn)
+{
pid_t pid ;
int wstat ;
- uint32_t nlong, nshort, n ;
+ unsigned int m = 0 ;
+ char const *argv[13 + n] ;
+ char fmtv[UINT_FMT] ;
+ char fmtt[UINT_FMT] ;
+ unsigned char oldstate[nstate] ;
+ if (!s6rc_live_state_read(g->dirs.live, oldstate, nstate))
+ strerr_diefu2sys(111, "read state in ", g->dirs.live) ;
+
+ argv[m++] = S6RC_EXTBINPREFIX "s6-rc" ;
+ argv[m++] = "-X" ; /* we already hold the lock */
+ argv[m++] = "-v" ;
+ argv[m++] = fmtv ;
+ fmtv[uint_fmt(fmtv, g->verbosity)] = 0 ;
+ if (timeout)
+ {
+ argv[m++] = "-t" ;
+ argv[m++] = fmtt ;
+ fmtt[uint_fmt(fmtt, timeout)] = 0 ;
+ }
+ if (dryrun)
+ {
+ argv[m++] = "-n" ;
+ argv[m++] = "1" ;
+ }
+ argv[m++] = "-l" ;
+ argv[m++] = g->dirs.live ;
+ argv[m++] = "--" ;
+ argv[m++] = h ? "start" : "stop" ;
+ while (*services) argv[m++] = *services++ ;
+ argv[m++] = 0 ;
+ pid = cspawn(argv[0], argv, (char const *const *)environ, CSPAWN_FLAGS_SIGBLOCKNONE, 0, 0) ;
+ if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ;
+ if (wait_pid(pid, &wstat) <= 0) strerr_diefu1sys(111, "wait for s6-rc") ;
+ if (wait_estatus(wstat) && g->verbosity)
+ {
+ unsigned char newstate[nstate] ;
+ if (!s6rc_live_state_read(g->dirs.live, newstate, nstate))
+ strerr_diefu2sys(111, "read state in ", g->dirs.live) ;
+ if (g->verbosity) s6f_report_state_change(n, oldstate, newstate, dbfn, h) ;
+ }
+
+ return wait_estatus(wstat) ;
+}
+
+static int live_startstop (char const *const *argv, int h)
+{
+ uint64_t wgolb = 0 ;
+ unsigned int timeout = 0 ;
+ uint32_t nlong, nshort ;
int livelock, compiledlock ;
size_t livelen = strlen(g->dirs.live) ;
- argv += GOL_argv(argv, rgolb, rgola, &wgolb, wgola) ;
+ argv += parse_options(argv, &wgolb, &timeout) ;
if (!*argv) strerr_dieusage(100, h ? "s6 live start services..." : "s6 live stop services...") ;
- if (wgola[GOLA_TIMEOUT])
- {
- if (!uint0_scan(wgola[GOLA_TIMEOUT], &t))
- strerr_dief1x(100, "timeout must be an integer (milliseconds)") ;
- }
s6f_lock(g->dirs.stmp, 0) ; /* leaks, it's fine */
char dbfn[livelen + 10] ;
memcpy(dbfn, g->dirs.live, livelen) ;
@@ -66,59 +116,45 @@ int live_startstop (char const *const *argv, int h)
strerr_diefu2sys(111, "take lock in ", g->dirs.live) ;
if (!s6rc_live_state_size(g->dirs.live, &nlong, &nshort))
strerr_diefu2sys(111, "read state size in ", g->dirs.live) ;
- n = nlong + nshort ;
- unsigned char oldstate[n] ;
- if (!s6rc_live_state_read(g->dirs.live, oldstate, n))
- strerr_diefu2sys(111, "read state in ", g->dirs.live) ;
- {
- size_t m = 0 ;
- char const *newargv[13 + argc] ;
- char fmtv[UINT_FMT] ;
- char fmtt[UINT_FMT] ;
-
- newargv[m++] = S6RC_EXTBINPREFIX "s6-rc" ;
- newargv[m++] = "-X" ; /* we already took the locks */
- newargv[m++] = "-v" ;
- newargv[m++] = fmtv ;
- fmtv[uint_fmt(fmtv, g->verbosity)] = 0 ;
- if (t)
- {
- newargv[m++] = "-t" ;
- newargv[m++] = fmtt ;
- fmtt[uint_fmt(fmtt, t)] = 0 ;
- }
- if (wgolb & GOLB_DRYRUN)
- {
- newargv[m++] = "-n" ;
- newargv[m++] = "1" ;
- }
- newargv[m++] = "-l" ;
- newargv[m++] = g->dirs.live ;
- newargv[m++] = "--" ;
- newargv[m++] = h ? "start" : "stop" ;
- while (*argv) newargv[m++] = *argv++ ;
- newargv[m++] = 0 ;
- pid = cspawn(newargv[0], newargv, (char const *const *)environ, CSPAWN_FLAGS_SIGBLOCKNONE, 0, 0) ;
- if (!pid) strerr_diefu2sys(111, "spawn ", newargv[0]) ;
- }
- if (wait_pid(pid, &wstat) <= 0) strerr_diefu1sys(111, "wait for s6-rc") ;
- if ((WIFEXITED(wstat) && !WEXITSTATUS(wstat)) || !g->verbosity)
- return wait_estatus(wstat) ;
-
- unsigned char newstate[n] ;
- if (!s6rc_live_state_read(g->dirs.live, newstate, n))
- strerr_diefu2sys(111, "read state in ", g->dirs.live) ;
- if (g->verbosity) s6f_report_state_change(n, oldstate, newstate, dbfn, h) ;
- return wait_estatus(wstat) ;
+ return run_s6rc_change(argv, env_len(argv), h, !!(wgolb & GOLB_DRYRUN), timeout, nlong + nshort, dbfn) ;
}
-void service_start (char const *const *argv)
+void live_start (char const *const *argv)
{
_exit(live_startstop(argv, 1)) ;
}
-void service_stop (char const *const *argv)
+void live_stop (char const *const *argv)
{
_exit(live_startstop(argv, 0)) ;
}
+
+void live_restart (char const *const *argv)
+{
+ uint64_t wgolb = 0 ;
+ unsigned int timeout = 0 ;
+ int e ;
+ unsigned int argc ;
+ uint32_t nlong, nshort ;
+ int livelock, compiledlock ;
+ size_t livelen = strlen(g->dirs.live) ;
+
+ argv += parse_options(argv, &wgolb, &timeout) ;
+ if (!*argv) strerr_dieusage(100, "s6 live restart services...") ;
+
+ argc = env_len(argv) ;
+ s6f_lock(g->dirs.stmp, 0) ;
+ char dbfn[livelen + 10] ;
+ memcpy(dbfn, g->dirs.live, livelen) ;
+ memcpy(dbfn + livelen, "/compiled", 10) ;
+ if (!s6rc_lock(g->dirs.live, 2, &livelock, dbfn, 1, &compiledlock, 1))
+ strerr_diefu2sys(111, "take lock in ", g->dirs.live) ;
+ if (!s6rc_live_state_size(g->dirs.live, &nlong, &nshort))
+ strerr_diefu2sys(111, "read state size in ", g->dirs.live) ;
+
+ e = run_s6rc_change(argv, argc, 0, !!(wgolb & GOLB_DRYRUN), timeout, nlong + nshort, dbfn) ;
+ if (e) _exit(e) ;
+ e = run_s6rc_change(argv, argc, 1, !!(wgolb & GOLB_DRYRUN), timeout, nlong + nshort, dbfn) ;
+ _exit(e) ;
+}
diff --git a/src/s6-frontend/s6-frontend-internal.h b/src/s6-frontend/s6-frontend-internal.h
index ef27c86..0f47003 100644
--- a/src/s6-frontend/s6-frontend-internal.h
+++ b/src/s6-frontend/s6-frontend-internal.h
@@ -27,8 +27,6 @@ extern void version (char const *const *) gccattr_noreturn ;
/* live */
-extern int live_startstop (char const *const *, int h) ;
-
extern void live (char const *const *) gccattr_noreturn ;
extern void live_help (char const *const *) gccattr_noreturn ;
extern void live_restart (char const *const *) gccattr_noreturn ;