dev-server: two ports sharing one explicit STDB_STATE_DIR leak a server #63
Labels
No labels
area:defold
area:docs
area:infra
area:protocol
area:testing
kind:bug
kind:chore
phase:breadth
phase:core
phase:hardening
phase:slice
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
yuris/spacetimedb-defold#63
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while reviewing #60 (which closes #54). Not fixed there: #54 removes the default collision, and thiscase needs an explicit shared state dir.
Reproduced on the #54 branch:
server_pid() cannot fix this: by step 3 the pid it would need is gone from the pidfile. The fix has to be earlier - refuse to start when the pidfile names a live server for a different port, or key the pidfile within the state dir by port.
Low priority. It requires deliberately pointing two ports at one STDB_STATE_DIR, which is exactly the configuration #54 stopped anyone reaching by accident.
Correction to this issue as filed, from the round-two review of #60.
I wrote that
server_pid()cannot address this because "the pid it needs isgone from the pidfile" and so "the fix has to be earlier". The first half is
true, the conclusion is not: the pid is still in
/proc, which is the source oftruth #60 just introduced.
Review demonstrated a ~6-line fallback inside
server_pidthat scans/procfor a cmdline containing both
--listen-addr 127.0.0.1:$PORTand--data-dir $DATA. It recovered the leaked server with no false positive onthe other port and none on a foreign state dir. No pidfile, no new dependency,
no pipeline.
So the option space is larger than this issue first suggested, and the cheapest
fix may well be inside
server_pidafter all. Leaving the priority as-is - itstill needs a deliberately shared state dir - but the next implementer should not
be sent past that option.
Closed by #73.
dev-server.shnow refuses to start when$PIDFILEholds a live server on a different port, instead of overwriting it with its own doomed child.server_pid()could not repair this after the fact — the first pid was already gone from the file — so the fix is refusing the overwrite.Leak reproduced on
mainfirst, two ports sharing/tmp/63-test:After, the same sequence exits 1 in 2.1s (vs 31.6s waiting out a ping timeout) with the pidfile intact, and
stopthen works — ping returns000, nothing left inpgrep.Review caught that the first fix was incomplete in the path the project's own harnesses use.
stop_serverends in an unconditionalrm -f "$PIDFILE", andrestart)called it beforestart_server— sorestarton the second port deleted the record the guard reads and reproduced #63 verbatim on the branch. Sincerestartis what both conformance harnesses drive, that was the common path rather than a corner case. The guard is now a function,refuse_foreign_state_dir(), called from the top ofstart_serverand fromrestart)beforestop_server.Untouched paths re-verified, because moving the check into
restartput the harnesses' own path at risk: same-portrestartstill succeeds and the server comes back; same-port re-invocation still reportsalready running; two ports with default state dirs still coexist (the #54 behaviour, both answering 200); a stale pidfile still lets a start proceed. Guard is Linux-only via/proc, degrading to previous behaviour elsewhere — the same tradeserver_pid()already made.shellcheckexit 0. Verified onmain@52dd72dalongside the rest of the milestone: native and HTML5 conformance pass,8 passed, 0 failed.