Merge pull request #28545 from bluca/softreboot_survive

pid1: add SurviveFinalKillSignal= to skip units on final sigterm/sigkill spree
This commit is contained in:
Luca Boccassi
2023-09-28 17:12:03 +01:00
committed by GitHub
13 changed files with 205 additions and 39 deletions
+55 -17
View File
@@ -20,8 +20,10 @@ if [ -f /run/testsuite82.touch3 ]; then
read -r x <&5
test "$x" = "oinkoink"
# Check that no service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" != "active"
# Check that the surviving services are still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" = "active"
test "$(systemctl show -P ActiveState testsuite-82-survive-argv.service)" = "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive-sigterm.service)" != "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active"
# All succeeded, exit cleanly now
@@ -43,8 +45,10 @@ elif [ -f /run/testsuite82.touch2 ]; then
systemd-notify --fd=3 --pid=parent 3<"$T"
rm "$T"
# Check that no service is still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" != "active"
# Check that the surviving services are still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" = "active"
test "$(systemctl show -P ActiveState testsuite-82-survive-argv.service)" = "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive-sigterm.service)" != "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active"
# Test that we really are in the new overlayfs root fs
@@ -57,6 +61,9 @@ elif [ -f /run/testsuite82.touch2 ]; then
mount --bind /original-root /run/nextroot
mount
# Restart the unit that is not supposed to survive
systemd-run -p Type=exec --unit=testsuite-82-nosurvive.service sleep infinity
# Now issue the soft reboot. We should be right back soon.
touch /run/testsuite82.touch3
systemctl --no-block soft-reboot
@@ -85,8 +92,10 @@ elif [ -f /run/testsuite82.touch ]; then
systemd-notify --fd=3 --pid=parent 3<"$T"
rm "$T"
# Check that no service survived, regardless of the configuration
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" != "active"
# Check that the surviving services are still around
test "$(systemctl show -P ActiveState testsuite-82-survive.service)" = "active"
test "$(systemctl show -P ActiveState testsuite-82-survive-argv.service)" = "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive-sigterm.service)" != "active"
test "$(systemctl show -P ActiveState testsuite-82-nosurvive.service)" != "active"
# This time we test the /run/nextroot/ root switching logic. (We synthesize a new rootfs from the old via overlayfs)
@@ -107,6 +116,9 @@ elif [ -f /run/testsuite82.touch ]; then
# Bind our current root into the target so that we later can return to it
mount --bind / /run/nextroot/original-root
# Restart the unit that is not supposed to survive
systemd-run -p Type=exec --unit=testsuite-82-nosurvive.service sleep infinity
# Now issue the soft reboot. We should be right back soon.
touch /run/testsuite82.touch2
systemctl --no-block soft-reboot
@@ -123,24 +135,50 @@ else
systemd-notify --fd=3 --pid=parent 3<"$T"
rm "$T"
# Create a script that can survive the soft reboot by ignoring SIGTERM (we
# do this instead of the argv[0][0] = '@' thing because that's so hard to
# do from a shell
T="/dev/shm/survive-$RANDOM.sh"
cat >$T <<EOF
survive_sigterm="/dev/shm/survive-sigterm-$RANDOM.sh"
cat >"$survive_sigterm" <<EOF
#!/bin/bash
trap "" TERM
systemd-notify --ready
rm "$T"
rm "$survive_sigterm"
exec sleep infinity
EOF
chmod +x "$T"
# This sets DefaultDependencies=no so that it remains running until the
# very end, and IgnoreOnIsolate=yes so that it isn't stopped via the
# "testsuite.target" isolation we do on next boot
systemd-run -p Type=notify -p DefaultDependencies=no -p IgnoreOnIsolate=yes --unit=testsuite-82-survive.service "$T"
chmod +x "$survive_sigterm"
survive_argv="/dev/shm/survive-argv-$RANDOM.sh"
cat >"$survive_argv" <<EOF
#!/bin/bash
systemd-notify --ready
rm "$survive_argv"
exec -a @sleep sleep infinity
EOF
chmod +x "$survive_argv"
# This sets DefaultDependencies=no so that they remain running until the very end, and
# IgnoreOnIsolate=yes so that they aren't stopped via the "testsuite.target" isolation we do on next boot,
# and will be killed by the final sigterm/sigkill spree.
systemd-run -p Type=notify -p DefaultDependencies=no -p IgnoreOnIsolate=yes --unit=testsuite-82-nosurvive-sigterm.service "$survive_sigterm"
systemd-run -p Type=exec -p DefaultDependencies=no -p IgnoreOnIsolate=yes --unit=testsuite-82-nosurvive.service sleep infinity
# Configure these transient units to survive the soft reboot - they will not conflict with shutdown.target
# and it will be ignored on the isolate that happens in the next boot. The first will use argv[0][0] =
# '@', and the second will use SurviveFinalKillSignal=yes. Both should survive.
systemd-run -p Type=notify --unit=testsuite-82-survive-argv.service \
--property SurviveFinalKillSignal=no \
--property IgnoreOnIsolate=yes \
--property DefaultDependencies=no \
--property After=basic.target \
--property "Conflicts=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
--property "Before=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
"$survive_argv"
systemd-run -p Type=exec --unit=testsuite-82-survive.service \
--property SurviveFinalKillSignal=yes \
--property IgnoreOnIsolate=yes \
--property DefaultDependencies=no \
--property After=basic.target \
--property "Conflicts=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
--property "Before=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
sleep infinity
# Check that we can set up an inhibitor, and that busctl monitor sees the
# PrepareForShutdownWithMetadata signal and that it says 'soft-reboot'.
systemd-run --unit busctl.service --property StandardOutput=file:/run/testsuite82.signal \