desktop: fix two managed-SSH-spawn bugs that break every fresh remote backend spawn - #96061
Closed
SmelterLabs wants to merge 1 commit into
Closed
desktop: fix two managed-SSH-spawn bugs that break every fresh remote backend spawn#96061SmelterLabs wants to merge 1 commit into
SmelterLabs wants to merge 1 commit into
Conversation
… backend
1. Quoting: the spawn payload wrapped expandRemotePath() output -- already
a shell-quoted fragment like "$HOME"'/...' -- in shq() again, so the
reservation/lock/owner_file variables hold the quote characters
literally and every mkdir "$reservation" fails forever (~5 min per
attempt spinning in the reservation loop while holding the box-global
update mutex; queued spawns starve behind it). The same double quoting
sits in the stale-reaper identity guards, making every reap REFUSE.
The lockfile-reuse path masks the bug for existing backends, so it
only bites on fresh spawns.
2. Bashism: lockfile publication used ${var//__PID__/$child} -- bash-only
substitution in a payload run under plain sh (dash on Ubuntu), which
aborts the script AFTER the serve was spawned. The client then saw an
unknown failure, ran its error cleanup (deleting the token file), and
the just-booted serve died on the missing token -- orphaning one serve
per attempt. Replaced with a POSIX sed substitution.
Adds two regression tests: payload variables must keep $HOME expandable
(no re-quoting), and the pid substitution must be POSIX sh. Both fail
against the previous code; all 89 remote-lifecycle tests pass with the
fix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4 tasks
1 task
Contributor
|
Merged via #96084 (rebase merge, commit pending confirmation below) — your commit cherry-picked onto current main with your authorship preserved. Both diagnoses were exactly right, and the turnaround was outstanding: the fresh-spawn path shipped in #95942 a few hours earlier with precisely the gap you hit (the engine suites drive scripted transports; the reuse path masks both bugs; only a live fresh spawn against a real remote exposes them — the test you ran). We added a dash-level E2E on top: the real buildSpawnCommand payload now executes under dash through the full reservation/mutex/publication sequence, and the pre-fix payload provably aborts. Third landed contribution of yours in this campaign — thank you. |
Contributor
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
Two bugs in the managed SSH spawn engine (
apps/desktop/electron/remote-lifecycle.ts) that together break every fresh remote backend spawn on a stock Ubuntu host. Found while running the current tip against a real remote (Ubuntu Server 24.04, dash as /bin/sh); the lockfile-reuse path masks both bugs for already-running backends, which is likely why they went unnoticed.Bug 1 — double shell-quoting in the spawn payload (and the stale reaper)
expandRemotePath()already returns a shell-quoted fragment like"$HOME"'/.hermes/...'.buildSpawnCommand()wrapped that output inshq()again, so the payload'sreservation/lock/owner_filevariables store the quote characters literally. Everymkdir "$reservation"then fails forever, and the reservation loop spins ~5 minutes per attempt while holding the box-global update mutex — with parallel spawn attempts queueing behind it on the flock. Observed live: 20+ payloads stacked on the mutex, every desktop connect timing out at 20s while the abandoned remote payloads kept spinning.The same double-quoting sits in
buildOwnedStaleTerminationCommand()'s identity guards, so every stale-backend reap REFUSEs on path mismatch.Fix: embed
expandRemotePath()output raw (it is already quoted), with comments marking the contract.Bug 2 — bashism in lockfile publication
The payload runs under plain
sh(dash on Ubuntu), but published the lockfile via${var//__PID__/$child}— bash-only substitution. dash aborts the whole script on it after the serve child was spawned; the client sees an unknown failure, runs its error cleanup which deletes the session token file, and the just-booting serve dies on the missing token — orphaning one serve process per attempt.Fix: POSIX
sedsubstitution.Tests
Two regression tests added to
remote-lifecycle.test.ts:$HOMEexpandable (no re-quoting afterexpandRemotePath())${var//}; pid substituted via sed)Both fail against the previous code; all 89 remote-lifecycle tests pass with the fix. Live-verified end to end against an Ubuntu 24.04 remote: fresh backend spawn in ~3s with correct
backend.lock.jsonpublication, and kill-recovery (dispatch probe -> retire -> respawn) in 12s.🤖 Generated with Claude Code