Recognise a running stack on the other loopback - #469
Closed
kevin9327 wants to merge 1 commit into
Closed
Conversation
Opening the desktop window a second time asks `already_running` whether the deployment it manages is up, so a person is shown OpenBot rather than a setup screen for a stack that is already running. The question was asked at `127.0.0.1` alone. Every other check on that port accepts either loopback, because a process binds whichever one its runtime resolved `localhost` to: `answering_at` (the readiness wait and the window's own navigation) and `port_already_taken` both ask both. So a server on `::1` was reported as nothing running -- the window offered to set up a deployment that was already up, and Start then refused on a port held by OpenBot itself, naming it as somebody else's process. The decision moves next to `answering_at` in `stack.rs`, which is what asks both addresses, and takes the port as an argument so a test can use one nothing else holds. `main.rs` keeps only the command.
kevin9327
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso and
tylerslaton
as code owners
September 9, 2026 22:52
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Contributor
|
Closing this as overtaken by main. |
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.
Open the desktop app, set OpenBot up, and leave it running. Close the window and open it again. The
window says "Set up OpenBot" for a stack that is already up, and pressing Start answers:
That is OpenBot's own server. There is nothing on screen that can stop it, because the window does
not believe it is running.
Why
A second window has no handles on a stack an earlier one raised, so
already_runningasks thedeployment itself: is there a stamp here, and does the API answer? The second half asked one address:
Everything else in the shell that asks about that same port accepts either loopback.
answering_atwalks
LOOPBACKS = ["127.0.0.1", "[::1]"], and its comment says why: "A process that binds one andnot the other is normal rather than broken: Node resolves
localhostto::1and bun to127.0.0.1, so which one a service ends up on depends on what started it." The readiness wait usesit,
app_urluses it to point the window at the app, and #453 broughtport_already_takenin linewith it last night.
already_runningis the one that was left behind, and it is the one that decides which screen aperson sees. So the two disagree in exactly the worst way: the screen says nothing is running, and
the guard in front of Start says the port is taken.
The fix
The decision moves into
stack.rs, beside the function that already asks both addresses, and takesthe port as an argument so a test can use one nothing else on the machine holds.
main.rskeeps the#[tauri::command]and nothing else — 21 lines out, 4 in — which also removes the last hand-rolledreqwestclient from that file.One behaviour change worth naming:
answering_at's client has a 3s timeout where the deleted onehad 2s, and it can now make two attempts. The check runs once, in the background of the setup
screen's first render, and a refused connection comes back immediately, so this is only visible on a
machine where a firewall drops rather than refuses.
Reproduction
Against
1c7bd92(origin/main), unmodified. A stamped deployment directory and a listeneranswering 200 on
[::1]:3001and nowhere else, handed straight to the shippedalready_running:The same probe with the listener on
127.0.0.1instead passes onmain, so it is the address thatdecides it and not the harness.
The four tests this PR ships, against
stack::already_running. Put the one-address client backinto the new function and 1 of the 4 fails:
The other three are the guard against over-correcting, and pass before and after: an answer on
127.0.0.1is still running, a stamp with nothing answering is not, and a directory this app neverinstalled into is not — that last one is what stops the window navigating to a stranger's server.
With the fix:
mainis 88; the four above are the difference.Verification
Run from
desktop/src-taurion Windows with Rust 1.98.0.cargo test --libis whatdesktop.ymlruns, so these are covered there.
Note on the changelog
The entry goes at the top of
## Unreleased, which is the same line every open PR touching thechangelog inserts at. Say the word if this needs rebasing onto whatever lands first.