From 8164ce1f50c03ef3c6548df0e3e1f1d499b90b88 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 18 Dec 2025 09:43:22 +0000 Subject: Add -W readyfd support to s6-l-i and s6-l-i-m --- doc/s6-linux-init-maker.html | 12 +++++++++++- doc/s6-linux-init.html | 14 +++++++++----- src/init/s6-linux-init-maker.c | 12 +++++++++++- src/init/s6-linux-init.c | 34 +++++++++++++++++++++++----------- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html index fb2880d..ab8044f 100644 --- a/doc/s6-linux-init-maker.html +++ b/doc/s6-linux-init-maker.html @@ -406,7 +406,17 @@ not be the default, but might be useful in some cases.
the container so the disks are synced on container halt. By default, no sync is performed. This option has no effect when the -C option is not present: on real machines, a sync is always -performed just before a system halt. +performed just before a system halt.
+ +
  • -W readyfd : ensure that at boot time, +before doing anything, s6-linux-init waits +for file descriptor readyfd to signal EOF. This is typically useful in +containers that implement the Docker synchronization mechanism, where the +container manager starts the container with a pipe open to the container's +descriptor 3, does its preparation, and closes the pipe to tell the container's +init that it can proceed. If this option is not given, or readyfd is 0, +s6-linux-init-maker makes no provision for synchronization and s6-linux-init +will boot without waiting.
  • Organization of the created directory

    diff --git a/doc/s6-linux-init.html b/doc/s6-linux-init.html index 4d800ce..efcbf6c 100644 --- a/doc/s6-linux-init.html +++ b/doc/s6-linux-init.html @@ -27,7 +27,7 @@ and execs into s6-svscan.

    Interface

    -     s6-linux-init [ -c basedir ] [ -p initial_path ] [ -s env_store ] [ -m umask ] [ -d slashdev ] [ -D initdefault ] [ -n | -N ] [ -C ] [ -B ] [ args... ]
    +     s6-linux-init [ -c basedir ] [ -p initial_path ] [ -s env_store ] [ -m umask ] [ -d slashdev ] [ -D initdefault ] [ -n | -N ] [ -C ] [ -B ] [ -W readyfd ] [ args... ]
     

    Early preparation

    diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c index 50aa7b8..fffbf2e 100644 --- a/src/init/s6-linux-init-maker.c +++ b/src/init/s6-linux-init-maker.c @@ -44,6 +44,7 @@ static unsigned int initial_umask = 0022 ; static unsigned int timestamp_style = 1 ; static unsigned int finalsleep = 3000 ; static unsigned int boot_verbosity = 1 ; +static unsigned int readyfd = 0 ; static int mounttype = 1 ; static int console = 0 ; static int logouthookd = 0 ; @@ -285,6 +286,12 @@ static inline int stage1_script (buffer *b, char const *data) || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ; satmp.len = sabase ; } + if (readyfd) + { + char fmtw[UINT_FMT] ; + if (buffer_puts(b, " -W ") < 0 + || buffer_put(b, fmtw, uint_fmt(fmtw, readyfd)) < 0) return 0 ; + } if (mounttype == 2) { if (buffer_puts(b, " -n") < 0) return 0 ; @@ -666,7 +673,7 @@ int main (int argc, char const *const *argv, char const *const *envp) subgetopt l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "V:c:u:G:1Lp:m:t:d:s:e:E:q:D:nNf:R:CBS", &l) ; + int opt = subgetopt_r(argc, argv, "V:c:u:G:1Lp:m:t:d:s:e:E:q:D:W:nNf:R:CBS", &l) ; if (opt == -1) break ; switch (opt) { @@ -691,6 +698,7 @@ int main (int argc, char const *const *argv, char const *const *envp) case 'C' : inns = 1 ; break ; case 'B' : nologger = 1 ; break ; case 'S' : innssync = 1 ; break ; + case 'W' : if (!uint0_scan(l.arg, &readyfd)) dieusage() ; break ; default : dieusage() ; } } @@ -702,6 +710,8 @@ int main (int argc, char const *const *argv, char const *const *envp) strerr_dief3x(100, "base directory ", robase, " is not absolute") ; if (slashdev && slashdev[0] != '/') strerr_dief3x(100, "devtmpfs directory ", slashdev, " is not absolute") ; + if (readyfd && readyfd < 3) + strerr_dief1x(100, "readyfd cannot be 1 or 2") ; if (env_store) { if (env_store[0] != '/') diff --git a/src/init/s6-linux-init.c b/src/init/s6-linux-init.c index dfef029..dab96d0 100644 --- a/src/init/s6-linux-init.c +++ b/src/init/s6-linux-init.c @@ -28,7 +28,7 @@ #include "defaults.h" #include "initctl.h" -#define USAGE "s6-linux-init [ -v verbosity ] [ -c basedir ] [ -p initpath ] [ -s envdumpdir ] [ -m umask ] [ -d devtmpfs ] [ -D initdefault ] [ -n | -N ] [ -C ] [ -B ]" +#define USAGE "s6-linux-init [ -v verbosity ] [ -c basedir ] [ -p initpath ] [ -s envdumpdir ] [ -m umask ] [ -d devtmpfs ] [ -D initdefault ] [ -n | -N ] [ -C ] [ -B ] [ -W readyfd ]" #define dieusage() strerr_dieusage(100, USAGE) #define BANNER "\n s6-linux-init version " S6_LINUX_INIT_VERSION "\n\n" @@ -50,6 +50,7 @@ enum gola_e GOLA_MASK, GOLA_SLASHDEV, GOLA_INITDEFAULT, + GOLA_READYFD, GOLA_N } ; @@ -185,6 +186,7 @@ int main (int argc, char const **argv, char const *const *envp) { .so = 'm', .lo = "umask", .i = GOLA_MASK }, { .so = 'd', .lo = "slashdev", .i = GOLA_SLASHDEV }, { .so = 'D', .lo = "default-runlevel", .i = GOLA_INITDEFAULT }, + { .so = 'W', .lo = "readiness-fd", .i = GOLA_READYFD }, } ; char const *wgola[GOLA_N] = { @@ -195,9 +197,11 @@ int main (int argc, char const **argv, char const *const *envp) [GOLA_MASK] = 0, [GOLA_SLASHDEV] = 0, [GOLA_INITDEFAULT] = "default", + [GOLA_READYFD] = 0, } ; uint64_t wgolb = 0 ; - mode_t mask = 0022 ; + unsigned int mask = 0022 ; + unsigned int readyfd = 0 ; stralloc envmodifs = STRALLOC_ZERO ; char *tty = 0 ; unsigned int golc ; @@ -214,21 +218,29 @@ int main (int argc, char const **argv, char const *const *envp) argc -= golc ; argv += golc ; if (wgola[GOLA_VERBOSITY] && !uint0_scan(wgola[GOLA_VERBOSITY], &verbosity)) dieusage() ; if (wgola[GOLA_MASK] && !uint0_oscan(wgola[GOLA_MASK], &mask)) dieusage() ; + if (wgola[GOLA_READYFD]) + { + if (!uint0_scan(wgola[GOLA_READYFD], &readyfd)) dieusage() ; + if (readyfd && readyfd < 3) dieusage() ; + } hasconsole = fcntl(1, F_GETFD) >= 0 ; - if (wgolb & GOLB_INNS) + if (readyfd) { char c ; - ssize_t r = read(3, &c, 1) ; /* Docker synchronization protocol */ - if (r < 0) + ssize_t r = read(readyfd, &c, 1) ; /* Docker synchronization protocol */ + if (r == -1) { - if (errno != EBADF) strerr_diefu1sys(111, "read from fd 3") ; + if (errno != EBADF) strerr_diefu1sys(111, "read from readiness fd") ; } else { - if (r) if (verbosity) strerr_warnw1x("parent wrote to fd 3!") ; - close(3) ; + if (r) if (verbosity) strerr_warnw1x("parent wrote to readiness fd!") ; + close(readyfd) ; } + } + if (wgolb & GOLB_INNS) + { if (!wgola[GOLA_SLASHDEV] && hasconsole && isatty(1 + !(wgolb & GOLB_NOLOGGER))) { tty = ttyname(1 + !(wgolb & GOLB_NOLOGGER)) ; @@ -248,8 +260,8 @@ int main (int argc, char const **argv, char const *const *envp) /* at this point we're totally in the dark, hoping /dev/console will work */ nope = mount("dev", wgola[GOLA_SLASHDEV], "devtmpfs", MS_NOSUID | MS_NOEXEC, "") < 0 ; e = errno ; - if (open2("/dev/console", O_WRONLY) && open2("/dev/null", O_WRONLY)) return 111 ; - if (fd_move(2, 0) < 0) return 111 ; + if (open2("/dev/console", O_WRONLY) && open2("/dev/null", O_WRONLY)) _exit(111) ; + if (fd_move(2, 0) < 0) _exit(111) ; if (fd_copy(1, 2) < 0) strerr_diefu1sys(111, "fd_copy") ; if (nope) { @@ -263,7 +275,7 @@ int main (int argc, char const **argv, char const *const *envp) { if (!wgola[GOLA_SLASHDEV]) reset_stdin() ; if (open2("/dev/null", O_WRONLY) != 1 || fd_copy(2, 1) == -1) - return 111 ; + _exit(111) ; } if (!(wgolb & GOLB_HANDSOFFRUN)) -- cgit v1.3.1