From e03822f26e78a1c6ab37f8750b78595d6780bedc Mon Sep 17 00:00:00 2001 From: Kroese Date: Thu, 2 Jul 2026 20:14:05 +0200 Subject: [PATCH] feat: Improve shutdown logic (#1187) --- src/power.sh | 60 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/src/power.sh b/src/power.sh index 39ac390..82bb101 100644 --- a/src/power.sh +++ b/src/power.sh @@ -121,42 +121,58 @@ graceful_shutdown() { response="${response#*message\"\: \"}" [ -z "$response" ] && response="second signal" echo && error "Forcefully terminating because of: ${response%%\"*}" - { kill -15 -- "$pid" || :; } 2>/dev/null + kill -15 -- "$pid" 2>/dev/null || : fi - local cnt=0 abort=0 factor=3 offset=3 min max name - - [[ "$TIMEOUT" =~ ^[0-9]+$ ]] || TIMEOUT=115 - [ "$TIMEOUT" -ge 15 ] && factor=4 && offset=4 - [ "$TIMEOUT" -ge 30 ] && factor=5 && offset=5 - min=$(( factor + offset + 1 )) - [ "$TIMEOUT" -lt "$min" ] && TIMEOUT="$min" - elapsed=$(( SECONDS - start )) - max=$(( TIMEOUT - offset - elapsed )) - [ "$max" -lt "$factor" ] && max=$(( factor + 1 )) - abort=$(( max - factor )) + local name name="$(app)" - while [ "$cnt" -le "$max" ]; do + local term_grace=3 # seconds before loop ends to send SIGTERM + local cleanup_grace=3 # seconds reserved after the loop for cleanup + + if [[ ! "$TIMEOUT" =~ ^[0-9]+$ ]]; then + TIMEOUT=115 + fi + + if (( TIMEOUT >= 30 )); then + term_grace=5 + cleanup_grace=5 + elif (( TIMEOUT >= 15 )); then + term_grace=4 + cleanup_grace=4 + fi + + local cnt=0 sigterm_at=0 min wait_until elapsed timeout_left + + elapsed=$((SECONDS - start)) + timeout_left=$((TIMEOUT - elapsed)) + + min=$((term_grace + cleanup_grace + 1)) + (( timeout_left < min )) && timeout_left=$min + + wait_until=$((timeout_left - cleanup_grace)) + sigterm_at=$((wait_until - term_grace)) + + while (( cnt <= wait_until )); do sleep 1 & local slp=$! + # Stop waiting if the process has exited ! isAlive "$pid" && break - # Workaround for zombie pid + + # Workaround for stale/zombie QEMU pid file [ ! -s "$QEMU_PID" ] && break - if [ "$cnt" -ne "$abort" ]; then - if [ "$cnt" -gt 0 ] && [[ "$DEBUG" == [Yy1]* ]]; then - info "Waiting for $name to shut down... ($cnt/$max)" - fi - else - info "${name^} is still running, sending SIGTERM... ($cnt/$max)" - { kill -15 -- "$pid" || :; } 2>/dev/null + if (( cnt == sigterm_at )); then + info "${name^} is still running, sending SIGTERM... ($cnt/$wait_until)" + kill -15 -- "$pid" 2>/dev/null || : + elif (( cnt > 0 )) && [[ "${DEBUG:-}" == [Yy1]* ]]; then + info "Waiting for $name to shut down... ($cnt/$wait_until)" fi - wait $slp + wait "$slp" (( cnt++ )) done