The reboot path's container stops were unbounded, and stopped a different list than it restored

This commit is contained in:
Gmer4Lfe
2026-08-24 20:22:55 -04:00
parent eda411c0be
commit f2fddeb87d
+22 -1
View File
@@ -535,7 +535,28 @@ do_reboot() {
if is_docker_enabled && command -v docker >/dev/null 2>&1; then if is_docker_enabled && command -v docker >/dev/null 2>&1; then
mapfile -t _SYS_REBOOT_STOPPED < <(timeout "$DOCKER_TIMEOUT" docker ps --format '{{.Names}}' 2>/dev/null) mapfile -t _SYS_REBOOT_STOPPED < <(timeout "$DOCKER_TIMEOUT" docker ps --format '{{.Names}}' 2>/dev/null)
trap _trap_sys_reboot_restart EXIT trap _trap_sys_reboot_restart EXIT
timeout 60 docker ps -q 2>/dev/null | xargs -r docker stop >/dev/null 2>&1
# One container at a time, bounded individually, named when it fails.
#
# This was `timeout 60 docker ps -q | xargs -r docker stop`, where the timeout bounded
# only the left of the pipe — the stops themselves were unbounded, so a wedged daemon
# hung the reboot path indefinitely, on the half that actually stops the containers.
#
# Bounding the batch instead would mean picking a number against the container count,
# and being wrong either kills containers mid-write or never returns. Per container that
# question disappears: DOCKER_TIMEOUT is three times docker's own 10s stop grace, and
# holds whether this host runs five containers or fifty.
#
# It also reuses the list already read above rather than asking docker a second time,
# and matches stop_local_containers() in common.sh — loop, report by name, never xargs.
for _c in "${_SYS_REBOOT_STOPPED[@]}"; do
[[ -z "$_c" ]] && continue
if timeout "$DOCKER_TIMEOUT" docker stop "$_c" >/dev/null 2>&1; then
log " $_c stopped"
else
warn " $_c did not stop within ${DOCKER_TIMEOUT}s — continuing to reboot"
fi
done
fi fi
warn "Stopping User Scripts..." warn "Stopping User Scripts..."