fix(startup): load the application surface only after the startup page settled - #96
Closed
BIackFIame wants to merge 1 commit into
Closed
BIackFIame wants to merge 1 commit into
BIackFIame wants to merge 1 commit into
Conversation
…e settled Startup could fail with "ERR_ABORTED (-3) loading 'data:text/html...'" when the machine was busy. Since services start while the startup page loads, the application surface could start its navigation while the page was still committing or loading in its own renderer process. The application surface then committed first, and the page's ERR_ABORTED arrived afterwards, while the loadFile promise was still waiting. Electron's loadURL/loadFile promise takes the first main-frame did-fail-load it sees as its own, so the application load rejected with the startup page's abort and startup showed the failure page. Services still start while the page loads. The application surface now waits until the page load has settled, which it usually has by the time services are up. A close during the page load is still a quiet quit, and a real page error on a live window still fails startup. Measured with 40 sequential hidden launches per build, each helper process (renderer, GPU, utility) paused at random for 20 to 300 ms during the first navigations: origin/main failed 4 and 6 of 40, the same loop with this change 0 of 80. The build before "perf(startup): start services while the startup page loads" had 0 of 40. Without pauses all builds start 40 of 40; the median time to a ready window goes from 342 to 379 ms.
This was referenced Sep 29, 2026
Contributor
Author
|
Combined into #100 together with the other post-merge fixes, so they can be reviewed in one place. The commits are unchanged. |
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.
PR description for branch
fix/startup-aborted(one commit onmain20f6855). #94 and #95 are already merged, so this is a follow-up PR againstmain, not a comment on #94 or #95.Problem
On a busy machine, startup sometimes fails and shows the startup failure page:
It started with "perf(startup): start services while the startup page loads" (#94). Since that change, services start while the startup page (a
data:URL) is still loading. When services finish first,loadFilefor the application surface starts while the startup page is still committing or loading in its own renderer process. If the application surface commits first, the page'sdid-fail-load(-3, thedata:URL) arrives afterwards, while theloadFilepromise is still waiting. Electron'sloadURL/loadFilepromise takes the first main-frame load failure it sees as its own. So the application load rejects with the startup page's abort, andstartApplicationshows the failure page.The
supersededflag from #94 did not cover this. It kept the page's own promise from reporting the abort, but the error came through the application load's promise.Change
createWindowstill starts the page load without awaiting it. The page load now resolves to the error to report, or tonull. It never rejects.startApplicationstill starts services right away. Before it loads the application surface, it waits for the page load to settle. On a normal launch the page has usually finished by the time services are up.Tests
tests/startup-lifecycle.test.mjs: new sequencing test with injected fakes. It fails onmain(the application surface loads while the page is still pending). It passes with this change and also covers a real page error and a close while waiting.npm run typecheck, full suite (--test-concurrency=2, 1155/1155),electron-vite build: pass.Launch loop
Sequential hidden launches with a throw-away HOME and the keychain stubbed. Each launch runs until the window is ready or startup fails. Plain launches fail too rarely to measure: 0 of 40 on every build, including
main. To make the race reproducible, the loop pauses a random helper process (renderer, GPU or utility) three times during the first navigations, for 20 to 300 ms each (SIGSTOP/SIGCONT). This is the kind of descheduling a loaded machine produces.Every failure has the same trace: the page's
did-fail-load -3arrives after the application surface committed, and then comes "startup failed" with thedata:URL.Cost: without pauses, the median time from launch to a ready window goes from 342 ms to 379 ms (40 launches each). The application surface now starts after the page has loaded (about 85 ms after the page load starts) instead of when services are up (about 45 ms). For reference, the parent of the #94 startup commit, where the page and services ran one after the other, measured 457 ms in the same loop. That build has different renderer code, so the comparison is only approximate.