Claude/daemon install loop glaloq#43
Merged
Merged
Conversation
Re-running the daemon install over an already-running service wrote the new unit file / exe / params but never re-launched the process, so the old binary and settings kept running: `systemctl start` no-ops on an active unit and `nssm start` no-ops on a running service. Linux install now uses `systemctl restart` (starts if stopped, re-launches if running); Windows stops the service before starting so the freshly-set Application/AppParameters take effect. Added runner tests pinning both paths. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MCtUhn1rJhuh9k1qVMr31H
start_detached() skipped the spawn whenever a daemon was already answering on the control port, so re-running setup with Windows login startup left the OLD daemon (old build, old config) running — the same reinstall gap just fixed for the service paths. It now replaces the running daemon, in the order that's safe: remove any leftover daemon *service* registration first (its manager would resurrect a killed daemon and fight the fresh one over the port, and would double-start it at the next boot), then stop whatever process is listening on the daemon port via the existing terminate->kill ladder, then spawn. The port scan never targets our own process, non-listeners, or other ports. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MCtUhn1rJhuh9k1qVMr31H
…hing it An in-place re-install could inherit stale settings from the old registration: `nssm install` no-ops on an existing service and the per-setting `set` calls only overwrite what the new install specifies — so empty args skipped the AppParameters set (a dev install's `-m palctl.daemon` survived into a frozen re-install and broke it), and ObjectName was never reset back to LocalSystem after an --as-user install. install_service now goes stop -> remove -> register -> start whenever the service already exists, so the registration is exactly what this install specifies. Fresh installs skip the removal. This also supersedes the previous stop-before-start fix: the service is never left running across the re-registration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MCtUhn1rJhuh9k1qVMr31H
Re-running setup with a different background-startup choice left the
previous mechanism behind:
- login -> service kept the HKCU Run key, so the next login spawned a
second daemon that fought the service over the control port; and the
fresh service couldn't bind the port while the old login-startup
daemon still held it, so NSSM restart-looped the new daemon while the
old one kept serving. install_service now drops the Run key, registers
with start=False, clears the port, then starts.
- Unticking the background group ("none") did nothing at all. It now
removes both mechanisms and stops the running daemon — the same
"unticking actually turns it off" contract the Discord toggle
documents.
- Switching AWAY from a registered daemon service needs admin to remove
it; preflight now asks for elevation in that case instead of letting
the removal fail silently and claiming success.
- The wizard pre-selects "Windows service" when that's what is
registered, instead of silently defaulting back to login startup on a
re-run.
- Linux: a stray non-service daemon (dev checkout run by hand) is
stopped before the unit starts instead of crash-looping it; the unit's
own daemon is left to systemctl restart.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCtUhn1rJhuh9k1qVMr31H
…I install-startup complete Gap 1 — `palctl-daemon install-startup` on the CLI only wrote the Run key, which takes effect at the NEXT login, leaving an old daemon (or a leftover service) serving until then. It now runs the same replacement start_detached does for setup: remove a leftover daemon service, stop the old daemon, start the new one immediately. When the service can't be removed (not elevated), start_detached now verifies the removal and reports failure with the admin-prompt fix printed, instead of killing a process the service manager would resurrect and pretending it worked. Gap 2 — the wizard always defaulted the background-startup choice to "login", silently switching a "service" or "none" choice back on re-runs, because nothing distinguished "chose none" from a first run. Setup now persists the choice in config (daemon_startup: login/service/ none; "" = pre-upgrade config, which falls back to probing the registered service), and the wizard restores it — including unticking the background group for "none". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MCtUhn1rJhuh9k1qVMr31H
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 & why
How was it tested?
Checklist
pytestpassesruff check palctl testspassesgit commit -s) — opening this PR agrees to theCLA for its
contributions (see
CONTRIBUTING.md)
CHANGELOG.md