Public Access
Stop a dead WebView2 hanging Connect with the busy flag stuck
VaultViewModel.ConnectAsync awaited TerminalWorkspace.WaitForRendererAsync
with no timeout and no token, and RunAsync clears IsBusy only after the
work returns. Whether the renderer attaches at all depends on a runtime
this application does not install: with a missing or policy-blocked
Evergreen runtime, or an AppContainer that cannot reach loopback, the
socket never arrives — so Connect never returned, the window stayed
disabled on "Connecting…" for the rest of the session, and nothing on
screen said why. Left out of 0500e43 to keep that change focused, and
recorded in docs/platform-flags.md as worth fixing on its own merits.
The gate itself is unchanged and has to stay: TerminalDataPlane.SendAsync
drops frames when no renderer is attached rather than queueing them, so a
session opened before the renderer arrives loses its SessionOpened frame
and then streams output at a terminal that was never created. Only the
wait changed — RendererAttached.WaitAsync(timeout, cancellationToken),
with the command's own token threaded through.
Fifteen seconds, on TerminalWorkspaceOptions.RendererTimeout. Attaching is
normally near-instant, since WebView2 starts with the window and the page
has usually attached while the passphrase was still being typed, but a
first run on a cold profile creates a user-data directory and starts a
process tree of some thirty-five processes first, which on a loaded
machine is seconds rather than milliseconds. A renderer that will never
attach will not attach however long the wait is, so being generous costs
only how long a broken runtime takes to say so, while being tight costs
telling someone their runtime is broken when it was merely slow.
Injectable because both new tests would otherwise sit out that budget.
The timeout is caught in VaultViewModel rather than left to RunAsync's
generic handler, because TimeoutException.Message is "The operation has
timed out" — which sends someone looking at their network or their host.
The status now names the WebView2 runtime and says to install it.
TerminalWorkspaceTests covers the half that was missing: the wait gives up
(329 ms against a 250 ms budget) and obeys its token (2 ms against a
five-minute one). Before the bound, the first of those would have hung
rather than failed. ShellFlowTests never starts its workspace, which from
the view model's side is indistinguishable from a WebView2 that failed to
initialise, so it asserts that the status names WebView2 and that IsBusy
is cleared; changing the catch to another exception type makes it fail
with "The operation has timed out.", so neither assertion is vacuous. The
success path is untouched and still covered end to end by
TerminalEndToEndTests against a real sshd container, which now passes the
test's cancellation token.
One byproduct: the doc comment on WaitForRendererAsync carried two
double-encoded em dashes, fixed now that the block is rewritten.
This commit is contained in:
+13
-4
@@ -89,10 +89,19 @@ the case it was attached to. A process-level check cannot verify a rendering cla
|
||||
screenshot, and this defect shipped because one was never taken.
|
||||
|
||||
**What the first connection after unlocking actually depends on** is the `await
|
||||
workspace.WaitForRendererAsync()` in `VaultViewModel.ConnectAsync`, because `TerminalDataPlane.SendAsync`
|
||||
drops frames when no renderer is attached rather than queueing them. That await is the invariant; the
|
||||
control's visibility is not. It currently has no timeout, so a WebView2 that fails to initialise hangs
|
||||
Connect with the busy flag stuck — worth fixing on its own merits.
|
||||
workspace.WaitForRendererAsync(cancellationToken)` in `VaultViewModel.ConnectAsync`, because
|
||||
`TerminalDataPlane.SendAsync` drops frames when no renderer is attached rather than queueing them. That
|
||||
await is the invariant; the control's visibility is not.
|
||||
|
||||
It is now bounded — `TerminalWorkspaceOptions.RendererTimeout`, 15 s, plus the command's own token —
|
||||
because whether the renderer attaches at all depends on a runtime this application does not install. A
|
||||
missing or policy-blocked Evergreen runtime, or an AppContainer that cannot reach loopback, previously
|
||||
left Connect waiting forever with `IsBusy` stuck and nothing on screen to explain it. The gate is
|
||||
unchanged; only the wait is. Why 15 s and not less: attaching is near-instant in the normal case (the page
|
||||
attaches while the unlock screen is still up), but a cold WebView2 profile creates a user-data directory
|
||||
and starts its process tree first, and reporting a broken runtime to someone whose runtime was merely slow
|
||||
is the worse error. The timeout is caught in `VaultViewModel` and reported as a message naming WebView2,
|
||||
because `TimeoutException.Message` is "The operation has timed out" and names nothing.
|
||||
|
||||
**Hiding the WebView does not pause it.** With the holder window hidden, the page keeps
|
||||
`visibilityState: "visible"` and `requestAnimationFrame` keeps firing at roughly 115/s — Chromium does not
|
||||
|
||||
Reference in New Issue
Block a user