mirror of
https://github.com/systemd/systemd.git
synced 2026-08-10 17:14:31 +00:00
test: avoid using external commands in trap handlers
In #39675 the reported fail was as follows: 5580s [ 247.559994] TEST-13-NSPAWN.sh[1858]: Exported 93%. 5580s [ 247.659002] TEST-13-NSPAWN.sh[1858]: Exported 95%. 5580s [ 247.785893] TEST-13-NSPAWN.sh[1858]: Operation completed successfully. 5580s [ 247.923727] TEST-13-NSPAWN.sh[1858]: Exiting. 5580s [ 258.300406] TEST-13-NSPAWN.sh[1074]: + machinectl import-raw /var/tmp/container-export.raw container-raw-reimport 5580s [ 258.323328] TEST-13-NSPAWN.sh[1884]: The 'machinectl import-raw' command has been replaced by 'importctl -m import-raw'. Redirecting invocation. 5580s [ 258.659982] TEST-13-NSPAWN.sh[1884]: Failed to transfer image: Remote peer disconnected 5580s [ 258.734218] TEST-13-NSPAWN.sh[1074]: + at_exit Turns out that the real reason behind this fail is that the machine was under heavy load due to a busy-loop from the stub init. The cause of this is a bug in bash, where running commands that fork (i.e. not built-ins) can cause a permanent busy-loop due to a desync in trap handling if you send the signals to the bash process _just right_: [ 90.855318] TEST-13-NSPAWN.sh[1074]: + machinectl poweroff long-running long-running long-running [ 90.855318] TEST-13-NSPAWN.sh[1074]: + machinectl reboot long-running long-running long-running [ 90.928980] systemd-nspawn[1679]: ++ touch /poweroff [ 90.928980] systemd-nspawn[1679]: +++ touch /reboot [ 90.928980] systemd-nspawn[1679]: + : [ 90.928980] systemd-nspawn[1679]: + : [ 90.928980] systemd-nspawn[1679]: + wait [ 90.928980] systemd-nspawn[1679]: + : [ 90.928980] systemd-nspawn[1679]: + : [ 90.928980] systemd-nspawn[1679]: + wait [ 90.928980] systemd-nspawn[1679]: + : [ 90.928980] systemd-nspawn[1679]: + : [ 90.928980] systemd-nspawn[1679]: + wait ... $ journalctl --file TEST-13-NSPAWN-1.journal -o short-monotonic --no-hostname --grep "^\+ wait$" | wc -l 349734 So the stub-init was hammering the machine in a tight endless loop, which then caused systemd-importd to timeout when talking to D-Bus: [ 258.300096] TEST-13-NSPAWN.sh[1074]: + machinectl import-raw /var/tmp/container-export.raw container-raw-reimport ... [ 258.415319] systemd-importd[1859]: Unable to request name, failing connection: Method call timed out [ 258.483662] systemd-importd[1859]: Bus n/a: changing state RUNNING → CLOSING [ 258.605442] systemd-importd[1859]: Bus n/a: changing state CLOSING → CLOSED [ 258.659958] TEST-13-NSPAWN.sh[1884]: Failed to transfer image: Remote peer disconnected Given this is not our issue, let's work around it by using just built-ins from the trap handlers, which are not susceptible to this bug. Resolves: #39675
This commit is contained in:
committed by
Luca Boccassi
parent
812aa57d2c
commit
4d92c72b81
@@ -44,21 +44,27 @@ set -x
|
||||
|
||||
PID=0
|
||||
|
||||
trap 'touch /terminate; kill 0' RTMIN+3
|
||||
trap 'touch /poweroff' RTMIN+4
|
||||
trap 'touch /reboot' INT
|
||||
trap 'touch /trap' TRAP
|
||||
# Use only builtins in trap handlers to avoid forking. External commands
|
||||
# (like touch) cause bash to enter wait_for() for the child, and a nested
|
||||
# signal arriving during that wait triggers a bash bug where
|
||||
# run_interrupt_trap() clears catch_flag while other traps are still
|
||||
# pending, creating an orphaned pending_traps[] entry that makes 'wait'
|
||||
# busy-loop indefinitely.
|
||||
trap ': >/terminate; kill 0' RTMIN+3
|
||||
trap ': >/poweroff' RTMIN+4
|
||||
trap ': >/reboot' INT
|
||||
trap ': >/trap' TRAP
|
||||
trap 'exit 0' TERM
|
||||
trap 'kill $PID' EXIT
|
||||
|
||||
# We need to wait for the sleep process asynchronously in order to allow
|
||||
# bash to process signals
|
||||
sleep infinity &
|
||||
PID=$!
|
||||
|
||||
# notify that the process is ready
|
||||
touch /ready
|
||||
: >/ready
|
||||
|
||||
PID=$!
|
||||
while :; do
|
||||
wait || :
|
||||
done
|
||||
@@ -332,11 +338,11 @@ trap 'kill $PID' EXIT
|
||||
# We need to wait for the sleep process asynchronously in order to allow
|
||||
# bash to process signals
|
||||
sleep infinity &
|
||||
PID=$!
|
||||
|
||||
# notify that the process is ready
|
||||
touch /ready
|
||||
: >/ready
|
||||
|
||||
PID=$!
|
||||
while :; do
|
||||
wait || :
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user