liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 49d1703428f1f83bdc557517932796a1f031430e
parent 1d337588f9c7955a3ca1a912698a3f4e94cc4c18
Author: Daniel Barlow <dan@telent.net>
Date:   Sat, 15 Jun 2024 14:59:34 +0100

add s6-rc-up-tree: start reverse deps of controlled service

When s6-rc stops a service, it also stops everything that
depends on it. but when it starts a service it starts only
that service, so we have to go through the other services
depending on it and figure out if they should be started too.

Diffstat:
Mmodules/s6/default.nix | 17+++++++++++++++--
Mpkgs/default.nix | 2++
Mpkgs/liminix-tools/services/builder.sh | 2++
Apkgs/s6-rc-up-tree/default.nix | 4++++
Apkgs/s6-rc-up-tree/s6-rc-up-tree.sh | 24++++++++++++++++++++++++
Apkgs/s6-rc-up-tree/test-list | 7+++++++
Mpkgs/uevent-watch/default.nix | 6+++++-
Mpkgs/uevent-watch/watch.fnl | 2+-
8 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/modules/s6/default.nix b/modules/s6/default.nix @@ -8,7 +8,7 @@ let stdenvNoCC; inherit (lib.lists) unique concatMap; inherit (pkgs.pseudofile) dir symlink; - inherit (pkgs.liminix.services) bundle; + inherit (pkgs.liminix.services) oneshot bundle; s6-rc-db = let @@ -31,12 +31,25 @@ let isControlled s || (lib.lists.any isDependentOnControlled s.dependencies); + # all controlled services depend on this oneshot, which + # makes a list of them so we can identify them at runtime + controlled = oneshot { + name = "controlled"; + up = '' + mkdir -p /run/services/controlled + for s in $(s6-rc-db -d dependencies controlled); do + touch /run/services/controlled/$s + done + ''; + down = "rm -r /run/services/controlled"; + }; + defaultStart = builtins.filter (s: !(isDependentOnControlled s)) allServices; defaultDefaultTarget = bundle { name = "default"; - contents = defaultStart; + contents = defaultStart ++ [controlled]; }; servicesAttrs = { default = defaultDefaultTarget; diff --git a/pkgs/default.nix b/pkgs/default.nix @@ -98,6 +98,7 @@ in { run-liminix-vm = callPackage ./run-liminix-vm {}; s6-init-bin = callPackage ./s6-init-bin {}; s6-rc-database = callPackage ./s6-rc-database {}; + s6-rc-up-tree = callPackage ./s6-rc-up-tree {}; # schnapps is written by Turris and provides a high-level interface # to btrfs snapshots. It may be useful on the Turris Omnia to @@ -112,6 +113,7 @@ in { uevent-watch = callPackage ./uevent-watch {}; usb-modeswitch = callPackage ./usb-modeswitch {}; writeAshScript = callPackage ./write-ash-script {}; + writeAshScriptBin = callPackage ./write-ash-script/bin.nix {}; writeFennel = callPackage ./write-fennel {}; writeFennelScript = callPackage ./write-fennel-script {}; } diff --git a/pkgs/liminix-tools/services/builder.sh b/pkgs/liminix-tools/services/builder.sh @@ -16,6 +16,8 @@ done if test -n "$controller" ; then d=$(dirname $(cd ${controller} && ls -d */type)) echo "$d)" > $out/${name}/controller + # ^ why is there a closing paren here? + touch $out/${name}/dependencies.d/controlled fi for i in timeout-up timeout-down run notification-fd up down finish consumer-for producer-for pipeline-name restart-on-upgrade; do diff --git a/pkgs/s6-rc-up-tree/default.nix b/pkgs/s6-rc-up-tree/default.nix @@ -0,0 +1,4 @@ +{ + writeAshScriptBin +}: +writeAshScriptBin "s6-rc-up-tree" {} (builtins.readFile ./s6-rc-up-tree.sh) diff --git a/pkgs/s6-rc-up-tree/s6-rc-up-tree.sh b/pkgs/s6-rc-up-tree/s6-rc-up-tree.sh @@ -0,0 +1,24 @@ +service=$1 + +blocks="" +for controlled in $(cd /run/services/controlled/ && echo *); do + down=$(s6-rc -un0 change $controlled) + echo $controlled $down + if test -n "$down"; then + blocks="$blocks $controlled " + fi +done + +for s in $(s6-rc-db -d all-dependencies $service); do + for dep in $(s6-rc-db all-dependencies $s); do + case "$blocks" in + "* $dep *") + echo "not starting $s, blocked by $dep" + ;; + *) + echo "starting $s because $service" + s6-rc -u change $s + ;; + esac + done +done diff --git a/pkgs/s6-rc-up-tree/test-list b/pkgs/s6-rc-up-tree/test-list @@ -0,0 +1,7 @@ + +the service starts +uncontrolled descendants start +controlled descendants don't start +descendants which depend on a _different_ controlled service, which is down, don't start +descendants which depend on a _different_ controlled service, which is up, do start + diff --git a/pkgs/uevent-watch/default.nix b/pkgs/uevent-watch/default.nix @@ -8,17 +8,21 @@ , fennel , stdenv , fennelrepl +, s6-rc-up-tree +, makeWrapper }: stdenv.mkDerivation { name = "uevent-watch"; src = ./.; - nativeBuildInputs = [ fennelrepl ]; + nativeBuildInputs = [ fennelrepl makeWrapper ]; + propagatedBuildInputs = [ s6-rc-up-tree ]; installPhase = '' mkdir -p $out/bin cp -p ${writeFennel "uevent-watch" { packages = [fennel anoia nellie lualinux]; mainFunction = "run"; } ./watch.fnl} $out/bin/uevent-watch + wrapProgram $out/bin/uevent-watch --prefix PATH : "${s6-rc-up-tree}/bin" ''; checkPhase = '' fennelrepl ./test.fnl diff --git a/pkgs/uevent-watch/watch.fnl b/pkgs/uevent-watch/watch.fnl @@ -18,7 +18,7 @@ (fn start-service [devname linkname service] (match (if linkname (symlink (.. "/dev/" devname) linkname) true) - ok (pcall system (%% "s6-rc -b -u change %q" service)) + ok (pcall system (%% "s6-rc-up-tree %q" service)) (nil err) false)) (fn stop-service [linkname service]