fix(release): preserve initializer failure after verified cleanup

This commit is contained in:
2026-10-14 02:58:22 +08:00
parent 11a2b6643e
commit be22dd9c12
2 changed files with 123 additions and 10 deletions
+35 -10
View File
@@ -17,6 +17,7 @@ UNIT = "kf-postgres-initialize.service"
DATA = Path(dependencies.STORAGE["postgres"]["path"]) / "data"
RECEIPT = dependency_install.ROOT / "postgres.initialization.json"
CREDENTIAL = Path("/run/credentials") / UNIT / "bootstrap"
CGROUP = Path("/sys/fs/cgroup/kfonlinejudge.slice") / UNIT
def validate_password(contents: bytes) -> None:
@@ -152,7 +153,7 @@ def status() -> dict:
for line in service_install.systemctl(
"show",
UNIT,
"--property=LoadState,ActiveState,SubState,MainPID,Result,Description,Transient",
"--property=LoadState,ActiveState,SubState,MainPID,Result,Description,Transient,ControlGroup,ExecMainStatus",
).splitlines()
if "=" in line
)
@@ -296,7 +297,9 @@ def initialize(password_file: Path, password_sha: str) -> dict:
or time.monotonic() >= deadline
):
raise DeliveryError(
"database initialization failed/expired; partial state retained"
"database initialization failed/expired; partial state retained "
f"(result={actual.get('Result', 'unknown')}, "
f"exit={actual.get('ExecMainStatus', 'unknown')})"
)
time.sleep(0.5)
if actual.get("Result") != "success" or actual.get("MainPID") != "0":
@@ -319,14 +322,7 @@ def initialize(password_file: Path, password_sha: str) -> dict:
install.exclusive_file(RECEIPT, canonical(recorded), 0o600)
finally:
if dispatched:
actual = status()
if actual.get("LoadState") != "not-found":
if actual.get("Description") != description or actual.get("Transient") != "yes":
raise DeliveryError("foreign initialization unit; refused cleanup")
service_install.systemctl("stop", UNIT)
actual = status()
if actual.get("ActiveState") != "inactive" or actual.get("MainPID") != "0":
raise DeliveryError("database initialization cleanup unconfirmed")
stop_owned_unit(description)
return {
"initialized": True,
"reused": False,
@@ -337,6 +333,35 @@ def initialize(password_file: Path, password_sha: str) -> dict:
}
def stop_owned_unit(description: str) -> None:
"""A failed unit may be stopped; failure is never initialization success."""
actual = status()
if actual.get("LoadState") != "not-found":
if actual.get("Description") != description or actual.get("Transient") != "yes":
raise DeliveryError("foreign initialization unit; refused cleanup")
group = actual.get("ControlGroup", "")
if group and group != "/kfonlinejudge.slice/" + UNIT:
raise DeliveryError("foreign initialization cgroup; refused cleanup")
service_install.systemctl("stop", UNIT)
actual = status()
if actual.get("LoadState") != "not-found" and (
actual.get("Description") != description
or actual.get("Transient") != "yes"
or actual.get("ControlGroup", "") not in {"", "/kfonlinejudge.slice/" + UNIT}
):
raise DeliveryError("initialization unit ownership changed during cleanup")
if (
actual.get("ActiveState") not in {"inactive", "failed"}
or actual.get("MainPID") != "0"
or CGROUP.exists()
and (
(CGROUP / "cgroup.procs").read_text().strip()
or "populated 0" not in (CGROUP / "cgroup.events").read_text().splitlines()
)
):
raise DeliveryError("database initialization cleanup unconfirmed")
def main() -> None:
parser = argparse.ArgumentParser(description="Explicit bounded PostgreSQL initialization")
parser.add_argument("--password-file", type=Path)