Browse Source

Stop stage2 when a hook fails and the conf variable is set

Signed-off-by: Laurent Bercot <[email protected]>
Laurent Bercot 10 months ago
parent
commit
df0599220f

+ 7 - 4
README.md

@@ -42,7 +42,7 @@ Build the following Dockerfile and try it out:
 ```
 ```
 # Use your favorite image
 # Use your favorite image
 FROM ubuntu
 FROM ubuntu
-ARG S6_OVERLAY_VERSION=3.2.0.2
+ARG S6_OVERLAY_VERSION=3.2.0.3
 
 
 RUN apt-get update && apt-get install -y nginx xz-utils
 RUN apt-get update && apt-get install -y nginx xz-utils
 RUN echo "daemon off;" >> /etc/nginx/nginx.conf
 RUN echo "daemon off;" >> /etc/nginx/nginx.conf
@@ -828,6 +828,7 @@ then the catch-all logger is run as this user, which must be defined in your
 image's `/etc/passwd`. Every bit of privilege separation helps a little with security.
 image's `/etc/passwd`. Every bit of privilege separation helps a little with security.
 * `S6_BEHAVIOUR_IF_STAGE2_FAILS` (default = 0): determines what the container should do
 * `S6_BEHAVIOUR_IF_STAGE2_FAILS` (default = 0): determines what the container should do
 if one of the service scripts fails. This includes:
 if one of the service scripts fails. This includes:
+  * if the early stage2 hook exits nonzero (by default there's no hook)
   * if anything fails in `fix-attrs`
   * if anything fails in `fix-attrs`
   * if any old-style `/etc/cont-init.d` or new-style [s6-rc](https://skarnet.org/software/s6-rc/) oneshot fails
   * if any old-style `/etc/cont-init.d` or new-style [s6-rc](https://skarnet.org/software/s6-rc/) oneshot fails
   * if any old-style `/etc/services.d` or new-style [s6-rc](https://skarnet.org/software/s6-rc/) longrun is marked
   * if any old-style `/etc/services.d` or new-style [s6-rc](https://skarnet.org/software/s6-rc/) longrun is marked
@@ -886,9 +887,11 @@ is necessary for all the services to be brought up.
 will be interpreted as a shell excerpt that will be run in the early stage 2,
 will be interpreted as a shell excerpt that will be run in the early stage 2,
 before services are started. This can be used, for instance, to dynamically
 before services are started. This can be used, for instance, to dynamically
 patch the service database at run-time right before it is compiled and run.
 patch the service database at run-time right before it is compiled and run.
-The wrong value can prevent your container from running or endanger your
-security, so only use this if you know exactly what you are doing. When in
-doubt, leave this variable undefined.
+If the hook program exits nonzero and `S6_BEHAVIOUR_IF_STAGE2_FAILS` is 2 or more,
+the container will stop instantly. Please note that running the wrong hook program
+may prevent your container from starting properly, or may endanger your security;
+so only use this if you know exactly what you are doing. When in doubt, leave
+this variable undefined.
 * `S6_VERBOSITY` (default = 2): controls the verbosity of s6-rc, and potentially
 * `S6_VERBOSITY` (default = 2): controls the verbosity of s6-rc, and potentially
 other tools, at container start and stop time. The default, 2, is normally verbose:
 other tools, at container start and stop time. The default, 2, is normally verbose:
 it will list the service start and stop operations. You can make the container quieter
 it will list the service start and stop operations. You can make the container quieter

+ 26 - 10
layout/rootfs-overlay/package/admin/s6-overlay-@VERSION@/etc/s6-linux-init/skel/rc.init

@@ -9,6 +9,11 @@ trap : INT  # guard against ^C as much as possible
 prog=/run/s6/basedir/scripts/rc.init
 prog=/run/s6/basedir/scripts/rc.init
 top="$1" ; shift
 top="$1" ; shift
 
 
+haltwith () {
+  echo "$1" > /run/s6-linux-init-container-results/exitcode
+  exec /run/s6/basedir/bin/halt
+}
+
 if test -d /run/s6/container_environment ; then
 if test -d /run/s6/container_environment ; then
   s6-chmod 0755 /run/s6/container_environment
   s6-chmod 0755 /run/s6/container_environment
 fi
 fi
@@ -21,13 +26,26 @@ if test "$cv" -lt 0 ; then
   cv=0
   cv=0
 fi
 fi
 
 
+if b=`printcontenv S6_BEHAVIOUR_IF_STAGE2_FAILS` && eltest "$b" =~ '^[[:digit:]]+$' ; then : ; else
+  b=0
+fi
+
 if hook=`printcontenv S6_STAGE2_HOOK` && test -n "$hook" ; then
 if hook=`printcontenv S6_STAGE2_HOOK` && test -n "$hook" ; then
   set +e
   set +e
   $hook
   $hook
   r=$?
   r=$?
   set -e
   set -e
-  if eltest "$r" -gt 0 -a "$v" -gt 0 ; then
-    echo "$prog: warning: hook $hook exited $r" 1>&2
+  if test "$r" -gt 0 ; then
+    if test "$b" -ge 2 ; then
+      echo "$prog: fatal: hook $hook exited $r" 1>&2
+    elif test "$v" -ge 1 ; then
+      echo "$prog: warning: hook $hook exited $r" 1>&2
+    fi
+    if test "$b" -ge 2 ; then
+      haltwith "$r"
+    fi
+  elif test "$v" -ge 2 ; then
+    echo "$prog: info: hook $hook exited $r" 1>&2
   fi
   fi
 fi
 fi
 
 
@@ -49,12 +67,11 @@ s6-rc -v$v -u -t "$timeout" -- change "$top"
 r=$?
 r=$?
 set -e
 set -e
 
 
-if b=`printcontenv S6_BEHAVIOUR_IF_STAGE2_FAILS` && eltest "$r" -gt 0 -a "$b" =~ '^[[:digit:]]+$' -a "$b" -gt 0 ; then
+if test "$r" -gt 0 && test "$b" -gt 0 ; then
   echo "$prog: warning: s6-rc failed to properly bring all the services up! Check your logs (in /run/uncaught-logs/current if you have in-container logging) for more information." 1>&2
   echo "$prog: warning: s6-rc failed to properly bring all the services up! Check your logs (in /run/uncaught-logs/current if you have in-container logging) for more information." 1>&2
   if test "$b" -ge 2 ; then
   if test "$b" -ge 2 ; then
     echo "$prog: fatal: stopping the container." 1>&2
     echo "$prog: fatal: stopping the container." 1>&2
-    echo "$r" > /run/s6-linux-init-container-results/exitcode
-    exec /run/s6/basedir/bin/halt
+    haltwith "$r"
   fi
   fi
 fi
 fi
 
 
@@ -62,10 +79,10 @@ if test "$#" -gt 0 ; then
   cd `s6-cat < /run/s6/workdir`
   cd `s6-cat < /run/s6/workdir`
   set +e
   set +e
   arg0=`printcontenv S6_CMD_ARG0`
   arg0=`printcontenv S6_CMD_ARG0`
-  if b=`printcontenv S6_CMD_USE_TERMINAL` && eltest "$b" =~ '^[[:digit:]]+$' -a "$b" -gt 0 && b=`tty` ; then
-    arg0="redirfd -w 1 $b fdmove -c 2 1 $arg0"
+  if t=`printcontenv S6_CMD_USE_TERMINAL` && eltest "$t" =~ '^[[:digit:]]+$' -a "$t" -gt 0 && t=`tty` ; then
+    arg0="redirfd -w 1 $t fdmove -c 2 1 $arg0"
   fi
   fi
-  if b=`printcontenv S6_CMD_RECEIVE_SIGNALS` && eltest "$b" =~ '^[[:digit:]]+$' -a "$b" -gt 0 ; then
+  if s=`printcontenv S6_CMD_RECEIVE_SIGNALS` && eltest "$s" =~ '^[[:digit:]]+$' -a "$s" -gt 0 ; then
     $arg0 "$@" &
     $arg0 "$@" &
     cmdpid="$!"
     cmdpid="$!"
     echo "$cmdpid" > /run/s6/cmdpid
     echo "$cmdpid" > /run/s6/cmdpid
@@ -77,6 +94,5 @@ if test "$#" -gt 0 ; then
     r="$?"
     r="$?"
   fi
   fi
   set -e
   set -e
-  echo "$r" > /run/s6-linux-init-container-results/exitcode
-  exec /run/s6/basedir/bin/halt
+  haltwith "$r"
 fi
 fi