fix(update): verify updater-owning gateway restart out of cgroup - #77854
Open
joelshu1 wants to merge 3 commits into
Open
fix(update): verify updater-owning gateway restart out of cgroup#77854joelshu1 wants to merge 3 commits into
joelshu1 wants to merge 3 commits into
Conversation
added 3 commits
August 3, 2026 16:29
Delegate the terminal owner signal to a transient verifier outside the owning cgroup. Publish success only after a changed systemd PID/start generation and matching new-gateway readiness acknowledgement; persist actionable failure for no-transition, timeout, failed, stale, foreign, and duplicate paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fixes the post-update finalization path when
hermes updateis running inside one of the systemd gateway units it must restart.The updater now completes dashboard/backend cleanup and non-owning fleet work first, then delegates the updater-owning gateway's terminal restart to a transient verifier outside that gateway's cgroup. The verifier publishes success only after systemd reports a healthy replacement owner and the replacement gateway acknowledges readiness.
Root cause and supported reproduction
A gateway-triggered updater inherits the gateway's systemd cgroup.
setsid/start_new_session=Truechanges the process session, but does not move the updater out of that cgroup. The old order restarted the gateway fleet before_finish_dashboard_update_cleanup(). When the owning gateway exited, systemd tore down the cgroup and killed the updater before the dashboard/backend finalizer was reachable. The early result marker added by #8288 could therefore expose success while required finalization had not run.The first stripped-environment attempt was not a clean reproducer and is not used as proof. The supported reproduction is the second, journal-backed attempt on Linux user systemd: non-owning gateways moved to new PIDs, the updater reached the owning gateway, the journal recorded the updater worker/shell/process being killed during the owning unit's cgroup teardown, and the managed dashboard remained active on its unchanged pre-update PID. Its health endpoint still returned 200, which proved availability but not code freshness.
Ownership-aware finalization design
(scope, unit)instead of relying on a service-name substring.systemd-runverifier in a separate cgroup; only that verifier signals the old owner.ActiveState=activeSubState=runningMainPIDchangedsystemd-runandsystemctlwork behind prompt-free--no-ask-passwordplus root orsudo -ncapability resolution before any owner signal.Failure semantics
Accepted signal delivery without an owner transition is not success. Timeout, failed state, unchanged PID/start generation, changed owner without the matching readiness acknowledgement, stale/foreign nonce or unit data, duplicate invocation, verifier launch failure, and terminal-marker write failure remain actionable non-success.
A unit with
Restart=nois not auto-started: the verifier persistsverified=false, exits 1, emits no success marker, and provides explicit manual start/status guidance. The updater also avoids printing durable success while owner verification is pending.Related Issue
No exact issue covers the updater-owning cgroup/finalizer reachability defect.
Related history: #8288, #39166, and #72192.
This is not a duplicate of #47902: that PR persists dashboard web-action status through
hermes_cli/web_server.py; this PR fixes updater control-flow reachability and externally verifies the updater-owning systemd gateway. Their patch IDs and ownership protocols are different.Type of Change
Changes Made
hermes_cli/update_cmd.py: ownership-aware finalization order, durable result semantics, privilege-gated external verifier launch, and fail-closed owner handling.hermes_cli/update_owner_restart.py: nonce-bound out-of-cgroup owner transition/readiness verifier.gateway/run.pyandgateway/slash_commands.py: replacement-owner readiness acknowledgement and gateway update watcher integration.hermes_cli/dashboard_procs.pyandhermes_cli/main.py: ownership-aware dashboard/backend cleanup and managed restart verification.Restart=no, system/user scopes, marker state, stale/foreign requests, and full_cmd_update_implordering.How to Test
Run the focused owner/finalization suite:
Result: 71 passed, 0 failed across 4 files.
Run the broader updater/gateway suite:
Result: 251 passed, 0 failed across 27 files.
Run static and patch checks:
Result: Ruff 0.15.10 passed,
py_compilepassed,git diff --checkpassed, and the structured added-line secret scan reported 0 findings.Disposable Linux user-systemd verification from the independently reviewed candidate:
Restart=noowner: remained inactive with MainPID 0, verifier exited 1,verified=false, no success marker, and no temporary unit/path residue.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — N/A; no public command/config syntax changedcli-config.yaml.exampleif I added/changed config keys — N/A; no config keys changedCONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/A; no contributor workflow changedScreenshots / Logs
No screenshots. The reproducible journal evidence and disposable canary results are summarized above without including private runtime identifiers.