Skip to content

fix: single-instance daemon lock — refuse second hermes-node run - #123

Merged
blaspat merged 1 commit into
mainfrom
fix/single-instance-daemon-lock
Aug 28, 2026
Merged

blaspat merged 1 commit into
mainfrom
fix/single-instance-daemon-lock

Conversation

@blaspat

@blaspat blaspat commented Aug 28, 2026

Copy link
Copy Markdown
Owner

Summary

Multiple hermes-node daemons were stacking up on workmac when hermes-node run was invoked from several terminal sessions — each forked a new daemon and they fought over the same pairing token, so no node could stay connected.

Adds a single-instance guard backed by a daemon.lock file next to config.toml:

  • run (the daemon itself) refuses to start if a live PID holds the lock → daemon already running (PID N) — run 'hermes-node stop' first
  • runDetach (the CLI wrapper) refuses before forking, so the error lands on the terminal instead of inside daemon.log
  • Stale locks (dead PID) are reclaimed automatically, so a crash doesn't wedge future starts; the lock is removed on a clean exit

Test Plan

  • Live-lock refusal at both layers (before-fork + in-daemon)
  • Lock acquisition + cleanup on a fresh start
  • Stale-lock takeover
  • Full suite go test ./... passes; go vet + gofmt clean

Notes

  • Pure binary-level change — no launchd/systemd changes; works on workmac and homepc alike
  • TestReconnect_RecoversAfterServerRestart in internal/wire is a pre-existing flake (fails intermittently, unrelated to this change; passes in isolation and in full-suite runs)

Multiple daemon instances were stacking up on workmac when hermes-node run
was invoked from several terminal sessions; each forked a new daemon and
they fought over the same pairing token, so no node could stay connected.

Add a single-instance guard backed by a daemon.lock file next to config.toml:
- runRun (the daemon itself) refuses to start if a live PID holds the lock
- runDetach (the CLI wrapper) refuses before forking, so the error lands
  on the terminal instead of inside daemon.log
- stale locks (dead PID) are reclaimed automatically, so a crash doesn't
  wedge future starts; the lock is removed on a clean exit

Tests: live-lock refusal at both layers, lock acquisition + cleanup on a
fresh start, and stale-lock takeover.

Signed-off-by: Blasius Patrick <blasius.patrick@gmail.com>
@blaspat
blaspat merged commit 1bfda50 into main Aug 28, 2026
14 checks passed
@blaspat
blaspat deleted the fix/single-instance-daemon-lock branch August 28, 2026 02:15
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