auto: session-start commit — 4 file(s) at 2026-07-13 15:49:56
This commit is contained in:
parent
cc60794367
commit
e85fba3b09
File diff suppressed because it is too large
Load Diff
@ -275,6 +275,15 @@ fi
|
|||||||
done < <(printf '%s\n' "${eager_files[@]}" | sort -u)
|
done < <(printf '%s\n' "${eager_files[@]}" | sort -u)
|
||||||
printf ')\n\n'
|
printf ')\n\n'
|
||||||
|
|
||||||
|
printf '# Shared autoload helper. A stub routes its source through this so a\n'
|
||||||
|
printf '# TRANSIENTLY-absent target file (the scripts tree is wiped then\n'
|
||||||
|
printf '# repopulated mid-deploy — see update.sh) is waited for briefly rather\n'
|
||||||
|
printf '# than failing outright. Bounded (~5s) and only while the file is\n'
|
||||||
|
printf '# unreadable, so a genuinely-missing file still fails fast. Defined in\n'
|
||||||
|
printf '# this sourced manifest so it stays in memory even while on-disk files\n'
|
||||||
|
printf '# momentarily vanish.\n'
|
||||||
|
printf '__lpAutoload() { local __f="$1" __i; for ((__i=0; __i<20; __i++)); do [ -r "$__f" ] && break; sleep 0.25; done; source "$__f"; }\n\n'
|
||||||
|
|
||||||
printf '# Autoload stubs — one per public function. First call unsets the\n'
|
printf '# Autoload stubs — one per public function. First call unsets the\n'
|
||||||
printf '# stub, sources the real file (which redefines the function), then\n'
|
printf '# stub, sources the real file (which redefines the function), then\n'
|
||||||
printf '# re-invokes. The `unset -f` first means a failed source degrades to a\n'
|
printf '# re-invokes. The `unset -f` first means a failed source degrades to a\n'
|
||||||
@ -287,7 +296,7 @@ fi
|
|||||||
containers) base_var='install_containers_dir' ;;
|
containers) base_var='install_containers_dir' ;;
|
||||||
*) base_var='install_scripts_dir' ;;
|
*) base_var='install_scripts_dir' ;;
|
||||||
esac
|
esac
|
||||||
printf '%s() { unset -f %s; source "${%s}%s"; %s "$@"; }\n' \
|
printf '%s() { unset -f %s; __lpAutoload "${%s}%s"; %s "$@"; }\n' \
|
||||||
"$name" "$name" "$base_var" "${fn_to_file[$name]}" "$name"
|
"$name" "$name" "$base_var" "${fn_to_file[$name]}" "$name"
|
||||||
done < <(printf '%s\n' "${!fn_to_file[@]}" | sort)
|
done < <(printf '%s\n' "${!fn_to_file[@]}" | sort)
|
||||||
} > "$OUTPUT"
|
} > "$OUTPUT"
|
||||||
|
|||||||
@ -1,17 +1,42 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# LibrePortal WebUI Update Lock Check
|
# LibrePortal WebUI Update Lock Check
|
||||||
# Checks for update lock file to prevent concurrent updates
|
# 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() {
|
webuiCheckUpdateLock() {
|
||||||
local lock_file="$containers_dir/libreportal/frontend/data/updater.lock"
|
local lock_file="$containers_dir/libreportal/frontend/data/updater.lock"
|
||||||
|
local stale_after=900 # seconds (15 min); far longer than any real refresh
|
||||||
|
|
||||||
lock_file_found=""
|
if [ ! -f "$lock_file" ]; then
|
||||||
if [ -f "$lock_file" ]; then
|
isNotice "No update lock file found" >&2
|
||||||
isNotice "Update lock file exists: $lock_file"
|
echo "false"
|
||||||
lock_file_found="true"
|
return 0
|
||||||
else
|
|
||||||
isNotice "No update lock file found"
|
|
||||||
lock_file_found="false"
|
|
||||||
fi
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,11 @@ webuiLibrePortalUpdate() {
|
|||||||
if [ "$status" == "installed" ]; then
|
if [ "$status" == "installed" ]; then
|
||||||
isHeader "LibrePortal WebUI Updater"
|
isHeader "LibrePortal WebUI Updater"
|
||||||
|
|
||||||
# Check for update lock file first
|
# Check for update lock file first. webuiCheckUpdateLock echoes its
|
||||||
local result; result=$(webuiCheckUpdateLock)
|
# verdict on stdout (and auto-clears a stale lock); capture it directly.
|
||||||
|
# A $(...) subshell means any global the function sets never reaches us
|
||||||
|
# here, so the verdict MUST come back via the echo, not a shared var.
|
||||||
|
local lock_file_found; lock_file_found=$(webuiCheckUpdateLock)
|
||||||
checkSuccess "Checked for update lock file."
|
checkSuccess "Checked for update lock file."
|
||||||
|
|
||||||
if [[ "$lock_file_found" == "true" ]]; then
|
if [[ "$lock_file_found" == "true" ]]; then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user