Harden service reload recovery
This commit is contained in:
@@ -165,11 +165,19 @@ service_trigger_signature=abc" "$(cat "$TARGET_RELOAD_STATE")" "captured reload
|
||||
|
||||
printf 'format=1\n' >"$SNAPSHOT_FILE"
|
||||
printf 'old=1\n' >"$TARGET_RELOAD_STATE"
|
||||
printf 'stale=1\n' >"$TARGET_RELOAD_STATE.snapshot.100.200"
|
||||
printf 'stale=1\n' >"$TARGET_RELOAD_STATE.snapshot.interrupted"
|
||||
printf 'keep=1\n' >"$WORK_DIR/unrelated.snapshot.100.200"
|
||||
state_ucode clear-reload-state "$TARGET_RELOAD_STATE" "$SNAPSHOT_FILE"
|
||||
[ ! -e "$TARGET_RELOAD_STATE" ] ||
|
||||
fail "ucode should clear reload state file"
|
||||
[ ! -e "$SNAPSHOT_FILE" ] ||
|
||||
fail "ucode should clear reload state snapshot file"
|
||||
[ ! -e "$TARGET_RELOAD_STATE.snapshot.100.200" ] &&
|
||||
[ ! -e "$TARGET_RELOAD_STATE.snapshot.interrupted" ] ||
|
||||
fail "ucode should clear stale snapshots owned by the reload state file"
|
||||
[ -e "$WORK_DIR/unrelated.snapshot.100.200" ] ||
|
||||
fail "ucode should preserve unrelated snapshot files"
|
||||
|
||||
cat >"$WORK_DIR/service-dns-state.json" <<'JSON'
|
||||
{
|
||||
|
||||
@@ -62,6 +62,25 @@ require_pattern 'startup_config_fingerprint = external_config_fingerprint();' \
|
||||
"startup must snapshot runtime-relevant config after validation"
|
||||
require_pattern 'mark_pending_reload_if_config_changed(startup_config_fingerprint, "config_changed_during_start")' \
|
||||
"startup must queue reload when config changes while service is starting"
|
||||
awk '
|
||||
/function restart_runtime_for_reload\(\)/ { in_restart = 1 }
|
||||
in_restart && /status = start_impl\(\);/ { saw_start_impl = 1 }
|
||||
in_restart && /dnsmasq_configure\(true\)/ { duplicated_dns = 1 }
|
||||
in_restart && /write-current-reload-state-clean/ { duplicated_state = 1 }
|
||||
in_restart && /DNS_FAILOVER_UC.*start-runtime/ { duplicated_failover = 1 }
|
||||
in_restart && /^}/ { done = 1; exit }
|
||||
END { exit done && saw_start_impl && !duplicated_dns && !duplicated_state && !duplicated_failover ? 0 : 1 }
|
||||
' "$LIFECYCLE_UC" ||
|
||||
fail "reload fallback restart must reuse the complete start_impl path without duplicating finalization"
|
||||
require_pattern 'function abort_reload(status, runtime_changed)' \
|
||||
"reload failures must share one cleanup decision owner"
|
||||
require_pattern 'return abort_reload(status, true);' \
|
||||
"reload failures after runtime mutation must clean the partial runtime"
|
||||
cleanup_function_line="$(grep -nF 'function cleanup_failed_runtime()' "$LIFECYCLE_UC" | head -n1 | cut -d: -f1)"
|
||||
abort_function_line="$(grep -nF 'function abort_reload(status, runtime_changed)' "$LIFECYCLE_UC" | head -n1 | cut -d: -f1)"
|
||||
[ -n "$cleanup_function_line" ] && [ -n "$abort_function_line" ] &&
|
||||
[ "$cleanup_function_line" -lt "$abort_function_line" ] ||
|
||||
fail "cleanup_failed_runtime must be declared before abort_reload for ucode runtime calls"
|
||||
require_pattern 'pending_reload_log_context(reason)' \
|
||||
"startup queued reload must be visible in logs"
|
||||
require_pattern 'return "current reload";' \
|
||||
|
||||
Reference in New Issue
Block a user