Repository navigation
Conversation
Related: #42555 and #24351 are open ExecStop-marker implementations for the same systemd planned-stop behavior. This PR is a current-main salvage of #42555 using a dedicated helper module; maintainers should select one implementation. #43236 is the merged s6/container complement. |
monerostar
left a comment
There was a problem hiding this comment.
Ubuntu 26.04, kernel 7.0.0-28-generic, linux-5800x. Head 199f93fdcf.
Live unit hermes-gateway-main.service still has only
ExecStopPost=... gateway.cgroup_cleanup. No planned-stop ExecStop=.
Did not stop the live gateway.
origin/main generator emits the same Post-only pair.
This PR inserts
ExecStop=-/venv/bin/python -m gateway.systemd_planned_stop $MAINPID
before ExecStopPost=.
Isolated helper: main([our pid]) rc=0, marker file written,
planned_stop_marker_targets_self() is False (watcher leaves it),
consume_planned_stop_marker_for_self() is True. Invalid PID rc=2.
Focused tests: 5 passed in 2.36s.
Looks good from Linux. Current-main salvage vs #42555 / #24351. I only ran this tip.
|
Thanks @monerostar — I really appreciate you reproducing this on Linux/systemd and validating the exact PR tip and focused tests. The detailed verification is very helpful. |
fix(gateway): mark direct systemd stops as planned
|
|
Hi @alt-glitch — following up on the triage note. I checked the automated review observations: both generated systemd units already propagate Since #42555 and #24351 are older overlapping implementations, could you advise which direction maintainers would like to carry forward? #85901 is currently mergeable, preserves the original authorship, and its exact head |
199f93f to
b4583f9
Compare
b4583f9 to
1033097
Compare
|
Refreshed this PR onto the current upstream Follow-up changes since the previous review:
Verification on the rebased head:
Could you please re-review the refreshed PR and advise whether this implementation should be carried forward over the older overlapping #42555/#24351 implementations? |
42e1114 to
4816024
Compare
|
Rebased this PR onto the current upstream
Could a maintainer approve the fork workflows and re-review this final head? |
4816024 to
25ffe15
Compare
|
@NousResearch/hermes-agent-core — could a maintainer please approve the fork workflows for this PR and re-review the final head CI, Nix flake check, and Docker Build, Test, and Publish are currently Please also advise whether this current-main salvage should supersede the overlapping #42555/#24351 implementations. |
25ffe15 to
d2f81f4
Compare
|
Refreshed this PR onto current upstream
The fork branch was read back after the force-with-lease push and matches the new head. |
|
@NousResearch/hermes-agent-core — could a maintainer please approve/allow the fork workflows for the current PR head The previous approval request referenced the superseded head Please also re-review the current head after the workflows are approved. The exact head has been locally verified: 98 passed, 2 skipped; Ruff, py_compile, Windows-footguns, standalone helper smoke, generated systemd unit verification, and diff checks pass. |
|
@NousResearch/hermes-agent-core — gentle follow-up on the review request for PR #85901. The PR is mergeable and ready for maintainer review. Please let me know if any changes or a different direction are preferred. Thanks! |
d2f81f4 to
54d0b4f
Compare
Port the marker-only ExecStop design from NousResearch#42555 onto current main while preserving its original authorship. Generated user and system units now write the existing PID-scoped planned-stop marker before systemd delivers SIGTERM. Use a dedicated internal module instead of a recursive gateway stop command or signal-source inference. Unmarked SIGTERM keeps the existing unexpected-stop and non-zero exit behavior.
Mark ExecStop records as signal-handler-only so the cross-platform filesystem watcher cannot consume them before systemd delivers its implicit SIGTERM. This keeps planned-stop classification deterministic while preserving the default watcher behavior for Windows and other marker-driven stop paths. Emit journal-visible helper diagnostics on marker failures and add focused coverage for helper validation, watcher exclusion, marker consumption, and both generated systemd unit scopes.
54d0b4f to
5572445
Compare
|
Rebased this PR onto the current upstream
Verification on the exact final head:
The PR remains open and non-draft. GitHub currently reports |
What does this PR do?
Direct
systemctl stop/systemctl restartsends the generated systemd gateway an unmarkedSIGTERM. The gateway then classifies a normal service-manager stop as unexpected, which can produce a non-zero exit and an unwanted restart.This PR adds a best-effort, non-recursive
ExecStop=hook to both generated user and system units. The hook writes the existing PID-scoped planned-stop marker for$MAINPIDbefore systemd deliversSIGTERM.The helper is deliberately a top-level stdlib-only module:
python -m gateway.systemd_planned_stopwould first importgateway/__init__.pyand its full application dependency graph, which is unsafe while a service is being torn down. The new helper writes the same marker payload atomically and with owner-only permissions.The shutdown marker classification is centralized in
_classify_shutdown_signal(), which is used by the real POSIX signal handler. The cross-platform watcher still cannot consume systemd's marker before the implicitSIGTERMarrives. Existing CLI/Windows marker paths retain their watcher behavior by default, and raw/unmarkedSIGTERMkeeps its unexpected-shutdown behavior.Scope boundary: systemd does not run
ExecStop=when aType=notifyservice is stopped before reachingREADY=1; that pre-start activation case retains the existing behavior.This is a current-
mainsalvage of #42555, whose branch is stale and merge-conflicted. The original authorship is preserved.Related Issue
Fixes #42517.
Fixes #41631.
Follow-up to #42675 and #43236. Supersedes the stale implementation in #42555 while preserving its authorship.
Type of Change
Changes Made
hermes_systemd_planned_stop.py, a minimal stdlib-onlyExecStop=helper that validates$MAINPIDand writes the existing planned-stop marker.ExecStopPost=cleanup.SIGTERMbehavior.How to Test
Additional verification on Linux:
ruff check: passed;python3 -S -m hermes_systemd_planned_stopstandalone smoke: passed, including marker payload and0600permissions;systemd-analyze verifyon a generated unit: passed;git diff --check: passed.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
Screenshots / Logs
Not applicable. The standalone helper smoke and generated-unit verification passed, and the focused shutdown suite covers the real SIGTERM marker-classification path.
Refresh onto current upstream main (2026-09-09)
25ffe1530b4755095aa934b008b0c71e491400a2onto upstreammainat0e9fc2cc152b4a4d9fd736f107412ace2a0c2555.d2f81f4681b2b5efe222ec67e67783f0d310ab0a.main's four-field service identity.systemd-analyze verify, andgit diff --checkpassed.