fix(desktop): stop a racing relaunch from aborting the update install#970
Closed
huntharo wants to merge 1 commit into
Closed
fix(desktop): stop a racing relaunch from aborting the update install#970huntharo wants to merge 1 commit into
huntharo wants to merge 1 commit into
Conversation
On macOS a Squirrel/ShipIt bundle swap refuses to run while any instance of the target app is alive (SQRLInstallerErrorDomain -9 "App Still Running Error"). When the app is reopened during the brief, feedback-less quit -> install -> relaunch gap -- most often the user relaunching it because it looked stalled -- that instance strands the update in an abort/retry loop that only clears once the app happens to stay closed long enough. Add a cross-boot handoff marker written just before quitAndInstall(). On the next boot, if a swap is plausibly still in flight (fresh marker, still on the old version), the freshly launched instance exits immediately so ShipIt can finish and relaunch the updated build. The marker fails open -- missing, corrupt, stale, or already-on-target all boot normally -- with a 5 minute TTL so an aborted install can never wedge the app closed. Also pass isForceRunAfter=true to quitAndInstall() so ShipIt relaunches the updated app after the swap. It was leaving the app closed, which is what prompted people to reopen it mid-install in the first place. Deliberately not adding a single-instance lock (the app supports multiple instances sharing a profile per the runtime-config contract) nor a speculative ShipIt kickstart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
SQRLInstallerErrorDomain -9"App Still Running Error". Reopening the app during the brief, feedback-less quit → install → relaunch gap (typically the user relaunching it because it looked stalled) strands the update in an abort/retry loop that only clears once the app happens to stay closed long enough.update-handoff-marker.ts) written just beforequitAndInstall(). On the next boot, if a swap is plausibly still in flight (fresh marker, still on the old version), the freshly launched instance exits immediately so ShipIt can finish and relaunch the updated build. The marker fails open — missing / corrupt / stale / already-on-target all boot normally — with a 5-minute TTL so an aborted install can never wedge the app closed.isForceRunAfter=truetoquitAndInstall()so ShipIt relaunches the updated app after the swap. It was leaving the app closed, which is what prompted people to reopen it mid-install in the first place.Verification
pnpm teston the 3 affected files — 60 passed (8 new: the full marker decision matrix,isForceRunAfter+ marker assertions on the install path, and a boot-guard test proving no window opens while an install is mid-flight).pnpm typecheckclean;pnpm lint:eslint— 0 errors, 0 findings on the changed files.Notes
~/.pwragent/update-handoff.json— app-wide (not per-profile), since the update targets/Applications/PwrAgent.appregardless of profile.installDownloadedAppUpdate) setsisForceRunAfter=true; theautoInstallOnAppQuitpath is untouched, so a deliberate quit-with-pending-update doesn't force the app back open.launchctl kickstartof the ShipIt job: the launchd spawn stall observed pre-reboot cleared on reboot, and a kickstart adds shell-out/timing risk for a transient condition.