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.
This commit is contained in:
Daniel Barlow 2024-06-15 14:59:34 +01:00
parent 1d337588f9
commit 49d1703428
8 changed files with 60 additions and 4 deletions

View File

@ -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;

View File

@ -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 {};
}

View File

@ -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

View File

@ -0,0 +1,4 @@
{
writeAshScriptBin
}:
writeAshScriptBin "s6-rc-up-tree" {} (builtins.readFile ./s6-rc-up-tree.sh)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]