Closed general

Six main-thread stalls (21 to 76 s) during the first code-server load on a fresh box; dumps on winvm

John Lauer · 1mo ago ·closed by John Lauer

From the 1.0.343 virgin install on winvm (Azure D4s_v4), 2026-09-11, record docs/preprod/preprod-1.0.343-2026-09-11.md.

Between 14:17 and 14:24 UTC, while the editor pane first navigated to http://localhost:7380 and code-server booted its extension host, the main-watchdog logged MAIN THREAD BLOCKED six times: 21, 25, 25, 22, 76, 25 s. The window was frozen for those spans. The watchdog's restart tiers (90 s in setup, 180 s any time) were not reached, so nothing restarted; the six "=== Hydrogen Desktop started ===" banners in the log were the out-of-process hang-dump helper writing the startup banner (fixed in 1.0.344 by running the helper branch before setup_logging).

Last handler mark before each stall: wv2.NavigationStarting (the frame-nav logger, which does no work), so the blocking is elsewhere on the UI thread after that mark. Companion symptoms in the same window: "[cdp-gate] hbw::ai_threads_collect_contexts_inner held the gate for 46s / 56s", "[window-state] geometry probe timed out", "[control] vscode settings merge exceeded its 15s deadline (WSL management plane may be wedged)", "[auth] Network unreachable for /user" at a very high rate (+77 suppressed in 10 s: something in the front end retries /user in a tight loop while offline).

Dumps, written by the helper (valid, not the 0-byte in-process kind): C:\Users\azureuser\AppData\Roaming\hydrogen-desktop\hang-20260911-141747.dmp, -141901, -141926, -141954, -142048 (the 76 s one), -142353. The VM is kept for inspection (./winvm.sh stop when done).

Two things to look at: what the UI thread waits on during the OOPIF boot on a slow box (a synchronous wsl.exe or CDP call on the main thread would explain both the stall and the gate hold), and the /user retry loop while offline.

2 Replies

John Lauer · 1mo ago

Triaged with John today: fix now, joined with a report from a new user this week whose setup stopped at "Wait for code-server" (120 s timeout) on a fresh box. Same window, the first boot of code-server on a fresh install, two symptoms: code-server not listening in time, and ah's own main thread freezing while the extension host booted. Plan: pull the hang dumps from winvm and the setup log from the user's box, find what sits on the main thread and what code-server is doing in that window, fix both in ah, and verify with another virgin install on winvm.

John Lauer · 1mo ago

Root-caused from the five hang dumps, mitigation shipped in 1.0.392 and completed in 1.0.393, verified applied on winvm. Closing; the next virgin install on winvm is the real before/after, and I will record its stall count on this issue.

What the dumps say. Two of the five catch the main thread mid-stall, both with the same stack: EmbeddedBrowserWebView.dll (WebView2's own window procedure, dispatched from tao's message loop) calling through combase into a synchronous wait (ntdll NtWaitForAlertByThreadId). That is the UI thread blocked inside WebView2 waiting for the WebView2 browser process to answer a cross-process call. The other three dumps show the main thread already back in GetMessage, so the out-of-process helper fired after those stalls had ended. Nothing in Hydrogen's own code is on the blocking stack; the timeline puts the stalls in the first cold editor load (14:17 to 14:24), after the package install had finished (14:10), while code-server booted its extension host in the VM for the first time.

Why a 4-vCPU box: the VM's extension-host boot pegs the CPUs, the WebView2 browser process on the host starves, and any window message WebView2 has to answer synchronously waits on it.

The lever is scheduling, not code on the stack: Hydrogen now runs at above-normal priority (SetPriorityClass at startup, 1.0.392) and, because the WebView2 browser process does not inherit that class (measured: hydrogen AboveNormal, msedgewebview2 Normal after 1.0.392), four bounded passes after start raise every msedgewebview2.exe under Hydrogen's process tree (1.0.393). Verified on winvm: hydrogen 1.0.393 AboveNormal, all 8 WebView2 processes AboveNormal, log lines at +20 s and +60 s. The VM (vmmem, spawned by the WSL service) keeps normal priority, so the interactive window wins contention with the extension-host boot.

What I could not do here: reproduce the virgin condition. A cold extension-host restart on the already-set-up winvm produced zero stalls before the fix, so the stalls need the true first load (fresh extensions, cold disk, first WebView2 launch). That is the preprod virgin-install run, and its stall count goes here when it next runs.

The "Wait for code-server" 120 s timeout a new user hit is the earlier half of the same cold first boot; the report button that shipped for #4 is how the next such user sends us that log.

Log in to reply.