Fix systemd oneshot upgrade handoff deadlock
This commit is contained in:
1 parent
56fbcdad74
commit
898df2e926
5 files changed
+190
-20
No files matched your search
@@ -40,7 +40,8 @@ done
|
||||
need systemctl; need flock
|
||||
# This lock excludes two coordinators, independently from ordinary backup jobs.
|
||||
exec 8>/run/app-backup-upgrade.lock
|
||||
if [[ $UP_WORKER == true ]]; then flock -w 60 8; else flock -n 8 || die 'Another updater is preparing/running'; fi
|
||||
# Workers install their persistent error reporting before waiting on this lock.
|
||||
if [[ $UP_WORKER == false ]]; then flock -n 8 || die 'Another updater is preparing/running'; fi
|
||||
|
||||
prompt() {
|
||||
local answer
|
||||
@@ -244,20 +245,34 @@ if [[ $UP_WORKER == false ]]; then
|
||||
sha256sum "$UP_STATE/candidate.conf" | cut -d ' ' -f 1 > "$UP_STATE/candidate.sha256"
|
||||
echo "Vorpruefung erfolgreich. Writer: $(tr '\n' ' ' < "$UP_STATE/writers")"
|
||||
echo 'Jetzt folgen Installation, ein vollstaendiges Backup und Remote-Restore-Pruefung.'
|
||||
printf 'QUEUED\n' > "$UP_STATE/result.txt"
|
||||
if [[ $UP_FOREGROUND == true ]]; then
|
||||
flock -u 9; flock -u 8
|
||||
exec bash "$UPDATE_ROOT/update.sh" --worker "$UP_STATE"
|
||||
fi
|
||||
# A new systemd service inherits no shell FDs; it acquires both locks itself.
|
||||
printf 'QUEUED\n' > "$UP_STATE/result.txt"
|
||||
systemd-run --unit=app-backup-upgrade --collect --property=Type=oneshot \
|
||||
# A oneshot start job completes only when ExecStart exits. Waiting for that
|
||||
# job while holding FD 8 deadlocks with the worker waiting for the same lock.
|
||||
# Only enqueue here; result.txt, not systemd-run's exit code, proves success.
|
||||
# The launcher must not keep copies of our locks; systemd starts a fresh worker.
|
||||
systemd-run --no-block --unit=app-backup-upgrade --collect --property=Type=oneshot \
|
||||
--property=TimeoutStartSec=24h --property=TimeoutStopSec=5min --property=KillMode=mixed \
|
||||
/bin/bash "$UPDATE_ROOT/update.sh" --worker "$UP_STATE" || {
|
||||
printf 'FAILED: systemd worker could not be started; installed package/config/timer unchanged.\n' > "$UP_STATE/result.txt"
|
||||
/bin/bash "$UPDATE_ROOT/update.sh" --worker "$UP_STATE" 8>&- 9>&- || {
|
||||
# Revoke the queued state while still holding the coordinator lock. Even
|
||||
# if systemd accepted the job but its reply failed, it must not install.
|
||||
printf 'FAILED: systemd submission failed; installed package/config/timer unchanged.\n' > "$UP_STATE/result.txt"
|
||||
cat "$UP_STATE/result.txt"
|
||||
echo "Details: sudo journalctl -u app-backup-upgrade.service -n 100 --no-pager"
|
||||
echo "Ergebnis: sudo cat $UP_STATE/result.txt"
|
||||
exit 1
|
||||
}
|
||||
echo 'Update laeuft unabhaengig von SSH weiter.'
|
||||
echo 'Verlauf: sudo journalctl -fu app-backup-upgrade.service'
|
||||
# Release the backup lock FIRST. Once FD 8 is free, the worker may acquire
|
||||
# both immediately; reversing the order can make its backup lock check fail.
|
||||
flock -u 9
|
||||
flock -u 8
|
||||
exec 9>&- 8>&-
|
||||
echo 'Update-Auftrag an systemd uebergeben; Ausfuehrung unabhaengig von SSH.'
|
||||
echo 'Abgeschlossen ist das Update erst bei SUCCESS in der Ergebnisdatei.'
|
||||
echo 'Verlauf: sudo journalctl -fu app-backup-upgrade.service --no-pager'
|
||||
echo "Ergebnis: sudo cat $UP_STATE/result.txt"
|
||||
exit 0
|
||||
fi
|
||||
@@ -289,6 +304,10 @@ worker_finish() {
|
||||
trap worker_finish EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
# Record lock timeouts in update.log/result.txt as well as journald. Previously
|
||||
# this wait happened before logging/traps, leaving only systemd's exit status.
|
||||
flock -w 60 8 || die 'Timed out waiting for update coordinator lock (60s); installation not started'
|
||||
[[ $(cat "$UP_STATE/result.txt") == QUEUED ]] || die 'Upgrade is not queued or submission was cancelled; rerun updater'
|
||||
printf 'RUNNING\n' > "$UP_STATE/result.txt"
|
||||
acquire_backup_lock
|
||||
export APP_BACKUP_INHERIT_LOCK=1
|
||||
|
||||
Reference in new issue
Block a user