Repository navigation
inbox: exit once its home is deleted, and with the test that started it - #80
Merged
Merged
Conversation
krishhgg
force-pushed
the
fix/test-inboxes-exit
branch
from
October 6, 2026 05:02
7bfdc4c to
40afc1e
Compare
A `need` that files a card starts an inbox in the background, and an inbox with an open card never reaches its idle exit. Tests file cards and leave them, so one `cargo test` run left 11 inboxes running for good. The inbox now checks on each idle tick that its home and database still exist, and exits when either is gone, with or without --keep. Debug builds also read TOKENSTASH_EXIT_WITH=<pid> and exit once that process has ended; release builds ignore it. The integration tests start the binary through one helper that sets it to the test's own pid, and leak-test.sh and agent-conformance.sh set it to the script's. inbox_exit.rs files a card in a scratch home and checks the inbox exits once a stand-in parent process ends, once the home is deleted, and once the database is deleted. Co-Authored-By: Claude <[email protected]>
… remade one The exit checks ran only after a second with no request, so a client asking more often than that kept a deleted home's inbox up. They now run once a second whether requests arrive or not. The inbox records its database's device and inode at start and exits when they change, so a home deleted and made again by another `need` before the next check no longer leaves the old inbox holding the port with the old proof key. The exit tests in inbox_exit.rs now send a /verify every 100 ms while they wait, and the_inbox_exits_once_its_home_is_made_again checks that the old inbox goes and the next `need` gets a link from a new one. The debug-only helpers there are compiled only in debug builds, and init_mode.rs no longer imports `Command`, which only its Linux test used. Co-Authored-By: Claude <[email protected]>
krishhgg
force-pushed
the
fix/test-inboxes-exit
branch
from
October 6, 2026 05:29
ced4313 to
c89774f
Compare
A reply that failed or stalled used to count as an exit, so a stuck inbox holding the port could pass. The test now keeps asking until the connection is refused. Co-Authored-By: Claude <[email protected]>
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 leaked
After a day of
cargo testandscripts/leak-test.shruns, this machine had 365target/debug/tokenstash inboxprocesses running, every one withTOKENSTASH_HOMEunder /tmp. Onmain, onecargo test --workspacerun leaves 11 of them: 7 fromhuman_only.rs, 2 frommcp_surface.rs, 1 frommcp_bind.rsand 1 frominit_mode.rs.Why
A
needthat files a card callsnotify::ensure_inbox, which startstokenstash inboxin the background. The inbox exits only after 30 idle minutes with no open cards. Tests file cards and do not answer them, so those inboxes never exit, and many of their temp homes stay on disk too.What changed
--keeptoo. A real user loses nothing, since there is nothing left to serve. The port also comes free: the old inbox answers/verifywith the proof key it read at start, so aneedin a recreated home would find it foreign and hand out no links.TOKENSTASH_EXIT_WITH=<pid>and exit once that process has ended. On Linux the check reads/proc/<pid>/statand counts a zombie as ended. Elsewhere it runskill -0. Release builds never read the variable, the same way they ignoreTOKENSTASH_TAILSCALE.ensure_inboxpasses its environment to the inbox it starts. Every integration test now starts the binary throughtests/common/mod.rs::tokenstash(), which sets the variable to the test process's pid. The pty run ininit_mode.rsclears the environment, so it sets the variable itself.leak-test.shandagent-conformance.shexport it as$$.Inboxguards ininbox_scope.rs,inbox_deadline.rsandremote_tailscale.rs) still kill and reap it on drop. They are unchanged apart from going through the helper.--keephelp text and the uninstall steps in the README now say that an inbox exits once its data directory is deleted.How it was verified
crates/cli/tests/inbox_exit.rs, 2.5 s. Each test files a card withneedin a scratch home and checks the inbox still answers 1.5 s later. It then removes one thing and waits up to 5 s for the port to close, sending a/verifyevery 100 ms meanwhile so the inbox is never idle for a second. The things removed are a stand-in parent (sleep 30, named inTOKENSTASH_EXIT_WITH), the home, and the database. A fourth test replaces the home with a new one where anotherneedhas run, expects the old inbox to exit, and expects the nextneedto print a card link. All four tests fail against the inbox onmain.cmd/inbox.rschecksprocess_aliveagainst a child process: running, a zombie (Linux), and reaped.cargo clippy --workspace --all-targets --locked -- -D warningspasses in debug and release, andcargo test --workspace --locked --release --no-runbuilds without warnings.cargo test --workspace --lockedpasses, and so doesbash scripts/leak-test.sh, on this branch and merged with the currentmain.target/debug/tokenstash, frompgrep -a tokenstash:main, 0 beforecargo test --workspaceand 11 inboxes after.🤖 Generated with Claude Code
The PR appears safe to merge; the exit tests no longer accept stalled inboxes.
What we checked:
inbox_exitsreturns success only after a refused connection. A failed or stalled reply does not satisfy that check.Summary
The inbox exits when its home or database disappears, when the database is replaced on Unix, or when a named process ends in debug builds. Test helpers and scripts tie background inboxes to their test run.
Reviews (4) · Last reviewed commit: "tests: an inbox counts as gone only once..."