Merge pull request #121021 from pennae/container-sigterm

nixos/nix-containers: use SIGTERM to stop containers
This commit is contained in:
Florian Klink 2021-04-30 21:35:16 +02:00 committed by GitHub
commit 44a0debca7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 11 deletions

View file

@ -35,6 +35,9 @@ let
''
#! ${pkgs.runtimeShell} -e
# Exit early if we're asked to shut down.
trap "exit 0" SIGRTMIN+3
# Initialise the container side of the veth pair.
if [ -n "$HOST_ADDRESS" ] || [ -n "$HOST_ADDRESS6" ] ||
[ -n "$LOCAL_ADDRESS" ] || [ -n "$LOCAL_ADDRESS6" ] ||
@ -60,8 +63,12 @@ let
${concatStringsSep "\n" (mapAttrsToList renderExtraVeth cfg.extraVeths)}
# Start the regular stage 1 script.
exec "$1"
# Start the regular stage 2 script.
# We source instead of exec to not lose an early stop signal, which is
# also the only _reliable_ shutdown signal we have since early stop
# does not execute ExecStop* commands.
set +e
. "$1"
''
);
@ -127,12 +134,16 @@ let
''}
# Run systemd-nspawn without startup notification (we'll
# wait for the container systemd to signal readiness).
# wait for the container systemd to signal readiness)
# Kill signal handling means systemd-nspawn will pass a system-halt signal
# to the container systemd when it receives SIGTERM for container shutdown;
# containerInit and stage2 have to handle this as well.
exec ${config.systemd.package}/bin/systemd-nspawn \
--keep-unit \
-M "$INSTANCE" -D "$root" $extraFlags \
$EXTRA_NSPAWN_FLAGS \
--notify-ready=yes \
--kill-signal=SIGRTMIN+3 \
--bind-ro=/nix/store \
--bind-ro=/nix/var/nix/db \
--bind-ro=/nix/var/nix/daemon-socket \
@ -259,13 +270,10 @@ let
Slice = "machine.slice";
Delegate = true;
# Hack: we don't want to kill systemd-nspawn, since we call
# "machinectl poweroff" in preStop to shut down the
# container cleanly. But systemd requires sending a signal
# (at least if we want remaining processes to be killed
# after the timeout). So send an ignored signal.
# We rely on systemd-nspawn turning a SIGTERM to itself into a shutdown
# signal (SIGRTMIN+3) for the inner container.
KillMode = "mixed";
KillSignal = "WINCH";
KillSignal = "TERM";
DevicePolicy = "closed";
DeviceAllow = map (d: "${d.node} ${d.modifier}") cfg.allowedDevices;
@ -747,8 +755,6 @@ in
postStart = postStartScript dummyConfig;
preStop = "machinectl poweroff $INSTANCE";
restartIfChanged = false;
serviceConfig = serviceDirectives dummyConfig;

View file

@ -111,6 +111,26 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
machine.succeed(f"nixos-container stop {id1}")
machine.succeed(f"nixos-container start {id1}")
# clear serial backlog for next tests
machine.succeed("logger eat console backlog 3ea46eb2-7f82-4f70-b810-3f00e3dd4c4d")
machine.wait_for_console_text(
"eat console backlog 3ea46eb2-7f82-4f70-b810-3f00e3dd4c4d"
)
with subtest("Stop a container early"):
machine.succeed(f"nixos-container stop {id1}")
machine.succeed(f"nixos-container start {id1} &")
machine.wait_for_console_text("Stage 2")
machine.succeed(f"nixos-container stop {id1}")
machine.wait_for_console_text(f"Container {id1} exited successfully")
machine.succeed(f"nixos-container start {id1}")
with subtest("Stop a container without machined (regression test for #109695)"):
machine.systemctl("stop systemd-machined")
machine.succeed(f"nixos-container stop {id1}")
machine.wait_for_console_text(f"Container {id1} has been shut down")
machine.succeed(f"nixos-container start {id1}")
with subtest("tmpfiles are present"):
machine.log("creating container tmpfiles")
machine.succeed(