diff --git a/misc/error_handler.func b/misc/error_handler.func index 72bb76787..b52f5c136 100644 --- a/misc/error_handler.func +++ b/misc/error_handler.func @@ -224,7 +224,81 @@ error_handler() { } # ============================================================================== -# SECTION 3: SIGNAL HANDLERS +# SECTION 3: CLEANUP HANDLERS +# ============================================================================== + +# ------------------------------------------------------------------------------ +# cleanup_failed_lxc() +# +# - Cleanup handler for failed LXC installations +# - Only prompts during install phase (when CTID is set) +# - Asks user if they want to remove the broken container +# - 60 second timeout - auto-removes if no response +# - Stops and destroys container on timeout or confirmation +# - Silent if CTID not set or container doesn't exist +# ------------------------------------------------------------------------------ +cleanup_failed_lxc() { + local exit_code=$? + + # Only cleanup on error and during install (CTID must be set) + if [[ $exit_code -eq 0 || -z "${CTID:-}" ]]; then + return 0 + fi + + # Check if container exists + if ! pct status "$CTID" &>/dev/null; then + return 0 + fi + + # Prompt user for cleanup + if declare -f msg_warn >/dev/null 2>&1; then + msg_warn "Installation failed for container ${CTID}" + else + echo -e "\n${YW}[WARN]${CL} Installation failed for container ${CTID}" + fi + + # Ask for confirmation with 60s timeout + local response + echo -en "${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}" + + if read -t 60 -r response; then + # User provided input within timeout + if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then + # Empty (Enter) or Y/y = remove + : + elif [[ "$response" =~ ^[Nn]$ ]]; then + # N/n = keep for debugging + if declare -f msg_info >/dev/null 2>&1; then + msg_info "Container ${CTID} kept for debugging" + else + echo -e "${YW}Container ${CTID} kept for debugging${CL}" + fi + return 0 + fi + else + # Timeout reached - auto-remove + echo -e "\n${YW}No response - auto-removing container${CL}" + fi + + # Cleanup confirmed or timeout + if declare -f msg_info >/dev/null 2>&1; then + msg_info "Removing container ${CTID}" + else + echo -e "${YW}Removing container ${CTID}...${CL}" + fi + + pct stop "$CTID" &>/dev/null || true + pct destroy "$CTID" &>/dev/null || true + + if declare -f msg_ok >/dev/null 2>&1; then + msg_ok "Container ${CTID} removed" + else + echo -e "${GN}Container ${CTID} removed${CL}" + fi +} + +# ============================================================================== +# SECTION 4: SIGNAL HANDLERS # ============================================================================== # ------------------------------------------------------------------------------ @@ -275,7 +349,7 @@ on_terminate() { } # ============================================================================== -# SECTION 4: INITIALIZATION +# SECTION 5: INITIALIZATION # ============================================================================== # ------------------------------------------------------------------------------ @@ -288,7 +362,7 @@ on_terminate() { # * set -u: (optional) Exit on undefined variable (if STRICT_UNSET=1) # - Sets up traps: # * ERR → error_handler -# * EXIT → on_exit +# * EXIT → on_exit (+ cleanup_failed_lxc if in install context) # * INT → on_interrupt # * TERM → on_terminate # - Call this function early in every script @@ -299,7 +373,7 @@ catch_errors() { set -u fi trap 'error_handler' ERR - trap on_exit EXIT + trap 'cleanup_failed_lxc; on_exit' EXIT trap on_interrupt INT trap on_terminate TERM }