#!/bin/bash # LibrePortal WebUI Update Lock Check # Guards against concurrent WebUI data refreshes. # # Echoes its verdict ("true" = a live lock is held, skip; "false" = clear to # proceed) on stdout, and auto-clears a STALE lock. Callers must capture the # echo — `result=$(webuiCheckUpdateLock)` runs the function in a subshell, so a # global it set would never reach the caller (that was a real bug: the guard # read an always-empty global and so never actually blocked anything). # # Staleness matters because the lock's remover (webuiRemoveUpdateLock) is itself # a lazy-loaded function whose backing file can be transiently missing while the # scripts tree is wiped+repopulated mid-deploy. If that removal is skipped once, # the leftover lock would otherwise wedge EVERY future refresh. No single refresh # runs anywhere near this long, so a lock older than the threshold is a leftover. webuiCheckUpdateLock() { local lock_file="$containers_dir/libreportal/frontend/data/updater.lock" local stale_after=900 # seconds (15 min); far longer than any real refresh if [ ! -f "$lock_file" ]; then isNotice "No update lock file found" >&2 echo "false" return 0 fi local now lock_mtime age now=$(date +%s 2>/dev/null || echo 0) lock_mtime=$(stat -c '%Y' "$lock_file" 2>/dev/null || echo 0) age=$(( now - lock_mtime )) if (( now > 0 && lock_mtime > 0 && age >= stale_after )); then isNotice "Stale update lock (${age}s old ≥ ${stale_after}s) — clearing and continuing." >&2 runFileOp rm -f "$lock_file" >/dev/null 2>&1 echo "false" return 0 fi isNotice "Update lock file exists: $lock_file" >&2 echo "true" return 0 }