Skip to content

fix: [sc-109762] Isolate the Linux auto-update helper from its own systemd cgroup - #104

Merged
mlataza merged 2 commits into
mainfrom
bug/sc-109762/linux-auto-update-leaves-the-agent-service
Aug 20, 2026
Merged

mlataza merged 2 commits into
mainfrom
bug/sc-109762/linux-auto-update-leaves-the-agent-service

Conversation

@mlataza

@mlataza mlataza commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • On Linux, the auto-update --update helper inherited the running service's systemd cgroup. Calling svc.Stop() (systemctl stop <unit>) let the default KillMode=control-group kill the helper along with the service it just stopped, before it could replace the binary or call svc.Start() — leaving the endpoint offline with no automatic recovery (client report, v1.5.1→v1.5.2).
  • The helper is now launched inside its own transient systemd scope (systemd-run --scope --collect, cmd/agent_smith/run_command_linux.go) so it's never a member of the unit's cgroup and survives the stop. macOS is unaffected/unchanged (launchd kills by BSD process group, not cgroup) and was split into its own file (run_command_darwin.go).
  • Closes a coverage gap in .github/actions/verify-auto-update: it only checked for "Updating agent" and that the last "Agent Smith started" line wasn't the IT version — but that line is the helper's own startup banner, logged before it stops the old service, so it already named the new version even when the helper was killed moments later and never restarted anything. Added baseline/delta assertions to integration-test.yml (helper's own "Service started" line, service-manager active check, fresh MQTT subscription, and a real post-update command round-trip) across all three platforms.
  • Documented in README's "Surviving Its Own systemd Stop (Linux)" section, cross-referenced from CLAUDE.md.

Test plan

  • go build/go vet/go test ./... on linux, darwin, and windows GOOS targets
  • golangci-lint run ./... clean
  • actionlint clean on the modified workflow
  • Dispatched integration-test.yml on this branch with os=allrun 32398088409, green on all three platforms, headSha matches branch HEAD
  • Confirmed the four new assertions ("update helper survived to restart the service", "service is active after auto-update", "fresh subscription after auto-update", "command completion after auto-update") passed on ubuntu-latest and macos-latest, exercising the real fix end-to-end against a live systemd unit

…stemd cgroup

The --update helper inherited the running service's cgroup, so calling
systemctl stop on its own unit let KillMode=control-group kill the helper
along with the service before it could restart it, leaving the endpoint
offline with no auto-recovery. The helper now runs in its own transient
systemd scope (systemd-run --scope) so it survives the stop.

Adds integration-test coverage that asserts the helper actually logs a
restart, the service is active, and it resubscribes after a Linux
auto-update, closing a gap where the existing check could pass even when
the helper never restarted anything.
Remove an unused helper left over from an earlier edit and reformat a call
site golines flagged. The Linux build tag meant a local darwin lint run
never analyzed this file; only GOOS=linux (as CI's ubuntu-latest job runs
natively) caught it.
@mlataza
mlataza merged commit 1448a2e into main Aug 20, 2026
12 checks passed
@mlataza
mlataza deleted the bug/sc-109762/linux-auto-update-leaves-the-agent-service branch August 20, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant