Restart Pulse service after failed auto-update (#1323)

The auto-update flow stops the Pulse service before applying updates.
If the update fails, the rollback path restored files but never
restarted the service. Since the main unit was explicitly stopped
(not crashed), systemd's Restart=always didn't rescue it.

Add restart-on-failure guards to both pulse-auto-update.sh and
install.sh so Pulse is always restarted after a failed update attempt.
This commit is contained in:
rcourtman 2026-03-07 10:46:19 +00:00
parent 64f3bfa922
commit c0b3a0e665
2 changed files with 57 additions and 16 deletions

View file

@ -29,6 +29,7 @@ CURRENT_INSTALL_CTID=""
CONTAINER_CREATED_FOR_CLEANUP=false
BUILD_FROM_SOURCE_MARKER="$INSTALL_DIR/BUILD_FROM_SOURCE"
DETECTED_CTID=""
STOPPED_PULSE_SERVICE=""
# Installer version - the major version this script is bundled with
INSTALLER_MAJOR_VERSION=5
@ -187,6 +188,35 @@ safe_systemctl() {
}
}
stop_pulse_service_for_update() {
local service_name="${1:-$(detect_service_name)}"
if ! command -v systemctl >/dev/null 2>&1; then
return 1
fi
if timeout 5 systemctl is-active --quiet "$service_name" 2>/dev/null; then
STOPPED_PULSE_SERVICE="$service_name"
print_info "Stopping existing Pulse service ($service_name)..."
safe_systemctl stop "$service_name" || true
sleep 2
return 0
fi
return 1
}
restart_stopped_pulse_service_on_failure() {
local exit_code=$?
if [[ "$exit_code" -ne 0 ]] && [[ -n "$STOPPED_PULSE_SERVICE" ]] && command -v systemctl >/dev/null 2>&1; then
print_info "Restarting Pulse service ($STOPPED_PULSE_SERVICE) after failed update"
safe_systemctl start "$STOPPED_PULSE_SERVICE" || true
fi
}
trap restart_stopped_pulse_service_on_failure EXIT
# Detect existing service name (pulse or pulse-backend)
detect_service_name() {
if ! command -v systemctl >/dev/null 2>&1; then
@ -2084,12 +2114,8 @@ download_pulse() {
# Detect and stop existing service BEFORE downloading (to free the binary)
EXISTING_SERVICE=$(detect_service_name)
if timeout 5 systemctl is-active --quiet $EXISTING_SERVICE 2>/dev/null; then
print_info "Stopping existing Pulse service ($EXISTING_SERVICE)..."
safe_systemctl stop $EXISTING_SERVICE || true
sleep 2 # Give the process time to fully stop and release the binary
fi
stop_pulse_service_for_update "$EXISTING_SERVICE" || true
cd /tmp
if ! command -v sha256sum >/dev/null 2>&1; then
@ -2696,11 +2722,7 @@ build_from_source() {
fi
service_name=$(detect_service_name)
if timeout 5 systemctl is-active --quiet "$service_name" 2>/dev/null; then
print_info "Stopping existing Pulse service ($service_name)..."
safe_systemctl stop "$service_name" || true
sleep 2
fi
stop_pulse_service_for_update "$service_name" || true
mkdir -p "$INSTALL_DIR/bin" "$INSTALL_DIR/scripts"
@ -3063,8 +3085,11 @@ start_pulse() {
if ! safe_systemctl start $SERVICE_NAME; then
print_info "Note: systemctl start failed (common in unprivileged containers)"
print_info "The service will start automatically when the container starts"
STOPPED_PULSE_SERVICE=""
return 0
fi
STOPPED_PULSE_SERVICE=""
# Wait for service to start
sleep 3
@ -3239,7 +3264,7 @@ main() {
SERVICE_NAME=$(detect_service_name)
backup_existing
systemctl stop $SERVICE_NAME || true
stop_pulse_service_for_update "$SERVICE_NAME" || true
create_user
download_pulse
setup_update_command
@ -3449,7 +3474,7 @@ main() {
fi
backup_existing
systemctl stop $SERVICE_NAME || true
stop_pulse_service_for_update "$SERVICE_NAME" || true
create_user
download_pulse
setup_update_command
@ -3504,7 +3529,7 @@ main() {
fi
backup_existing
systemctl stop $SERVICE_NAME || true
stop_pulse_service_for_update "$SERVICE_NAME" || true
create_user
download_pulse
setup_directories

View file

@ -140,10 +140,25 @@ detect_service_name() {
fi
}
restart_service_if_needed() {
local service_name=$1
local service_was_active=$2
if [[ "$service_was_active" == "true" ]]; then
log info "Starting Pulse service after failed update"
systemctl start "$service_name" || true
fi
}
# Perform the update
perform_update() {
local new_version=$1
local service_name=$(detect_service_name)
local service_was_active=false
if systemctl is-active --quiet "$service_name" 2>/dev/null; then
service_was_active=true
fi
log info "Starting update to $new_version"
@ -211,8 +226,7 @@ perform_update() {
cp -f "$backup_dir/VERSION" "$INSTALL_DIR/VERSION"
fi
# Restart service with old version
systemctl restart "$service_name" || true
restart_service_if_needed "$service_name" "$service_was_active"
# Clean up backup
rm -rf "$backup_dir"
@ -234,6 +248,8 @@ perform_update() {
if [[ -f "$backup_dir/VERSION" ]]; then
cp -f "$backup_dir/VERSION" "$INSTALL_DIR/VERSION"
fi
restart_service_if_needed "$service_name" "$service_was_active"
# Clean up backup
rm -rf "$backup_dir"