Skip to content

daemon: refuse a bind conflict with a diagnosis naming the incumbent - #9

Open
godspede wants to merge 1 commit into
mainfrom
fix/daemon-refuses-bind-conflict-with-diagnosis
Open

godspede wants to merge 1 commit into
mainfrom
fix/daemon-refuses-bind-conflict-with-diagnosis

Conversation

@godspede

@godspede godspede commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

A bare "address already in use" masked a week-long outage on one deployment
(famelos#11975): the managed unit's bind failure produced only that raw OS
error in its log, so a hand-started daemon serving the same port from a
different --config/data_dir looked, from any operator shell, exactly
like the managed one working. Nobody watching the failing unit's own log
could tell "no daemon" from "a DIFFERENT daemon already holds this port" --
that ambiguity is what let the outage run for over a week undetected.

Change

On a listen failure for either the public or admin address, Run now dials
the same address; if something answers, the returned error names the
conflict explicitly ("already serving: another process is already
listening on ...") instead of leaving the raw bind error to speak for
itself.

Deliberately not gated on errors.Is(listenErr, syscall.EADDRINUSE): I
tried that first, and Windows' invented syscall.EADDRINUSE does not match
what net.Listen actually returns there (confirmed empirically -- the
check silently never fired on a real Windows bind conflict). A direct dial
against the address is the portable signal instead, independent of how each
platform phrases the underlying error.

Test plan

  • go build ./...
  • go vet ./...
  • go test ./... (all packages green)
  • New regression test TestRun_RefusesWhenPublicPortHeldAndNamesTheConflict:
    starts one daemon, then starts a second with a different data_dir but
    the same public port, and asserts the second fails fast with a
    message containing "already serving" rather than a bare bind error.

A bare 'address already in use' masked a week-long outage
(famelos#11975): the managed unit's bind failure produced only that raw
OS error, so a hand-started daemon serving the same port from a
different --config/data_dir looked, from any operator shell, exactly
like the managed one working. Nobody watching the failing unit's own
log could tell 'no daemon' from 'a DIFFERENT daemon already holds this
port'.

On a listen failure for either the public or admin address, dial the
same address; if something answers, name the conflict explicitly
instead of leaving the raw bind error to speak for itself.

Deliberately not gated on errors.Is(listenErr, syscall.EADDRINUSE):
Windows' invented syscall.EADDRINUSE does not match what net.Listen
actually returns there (confirmed empirically against a real bind
conflict on Windows) -- a direct dial is the portable signal instead.
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