diff --git a/modules/s6/default.nix b/modules/s6/default.nix index 9d42f43..c299072 100644 --- 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 index ccf1875..a25a122 100644 --- 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 index 68abf67..47587c6 100644 --- 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 new file mode 100644 index 0000000..b6d0576 --- /dev/null +++ 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 new file mode 100644 index 0000000..51bf3b6 --- /dev/null +++ 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 new file mode 100644 index 0000000..e0b4ebe --- /dev/null +++ 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 index df8f45f..916fd45 100644 --- 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 index ffd48fe..64cf6b5 100644 --- 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]