What happened?
Summary
In UWP/AppContainer hosts, EmbeddedBrowserWebView.dll (WebView2 Runtime) notifies its UI thread of queued work by posting PostMessageW(hwnd, 0x401, 0, 0) (0x401 = WM_USER+1 = Chromium kMsgHaveWork). The posting site (RVA 0xE0E0C) has no CAS deduplication, so while producers (AppTaskRunner::PostTask) keep enqueueing during the drain, the drain re-posts on exit and the loop becomes self-sustaining at ~100–165 msgs/sec.
Each pass leaks kernel handles (Event ×27 / Section ×31). Handle growth itself consumes no significant memory — the memory impact is indirect: sustained handle growth makes renderers crash and WebView2 restarts them, until 400–717 msedgewebview2.exe processes exhaust free RAM (~98%) and freeze the machine. In contrast, during the 60 s probe run the handle count grows at the same rate while free RAM stays essentially flat — confirming the memory drain comes from the renderer process explosion, not from the handles themselves.
MinesweeperWebViewProbe.zip
Root cause: the missing CAS dedup at 0xE0E0C (point A) lets the task notification loop self-perpetuate. Proven by patch: memory-patching 0xE0E0C (call → mov eax,1) stops 0x401 completely, the process count stops growing and a 5-minute handle sample is completely stable — single root cause, no independent second leak. This is an SDK-level defect, not app-specific (HIT was reproduced on Windows 10/11 × Runtime 113/151 with a clean-room probe). Detailed analysis in the collapsible section below.
Detailed root-cause analysis (disassembly evidence) — click to expand
Mechanism (static + dynamic)
queue non-empty & flag==0
-> post_fn_A: PostMessageW(hwnd, 0x401, 0, 0) @0xE0E0C (no CAS dedup)
-> UI thread WndProc 0x260BD0 handles 0x401
-> 0x260E00 COM wrapper -> vtable dispatch -> drain 0xE14CB
-> drain clears head/tail (real consume)
-> producers keep enqueueing during drain
-> drain exit: head != tail -> re-post 0x401 @0xE16A7
-> infinite loop
Comparison with upstream Chromium (base/message_loop/message_pump_win.cc)
Dynamic counters (WinDbg, 1 min) — point A 0xE0E0C: 837 | point B 0x3962F9: 0 | normal-play baseline: 6,109/min (~102/s)
Causal proof (patch of point A, 1 min) — PostMessageW 0x401 counter grew by just +1 in the minute after the patch — a real stop, not a slowdown (the storm normally runs at hundreds of posts/min, so +1 means it fully ceased) | process count: growing → stable | 5-min handle sample: completely stable
Self-feeding ratio (per-thread PostTask, 1 min) — UI thread (0x401 chain): 40,570 (99.4%) | other threads: 242 (0.6%)
Impact — resource-exhaustion DoS (system freeze), not memory corruption, no sandbox escape.
Related: #5290 — crash in EmbeddedBrowserWebView with TaskRunner::PostTask on the stack; different symptom (abort crash vs memory-exhaustion process explosion) but likely the same AppTaskRunner task-dispatch subsystem.
Importance
Important. My app's user experience is significantly compromised.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
151.0.4129.78
SDK Version
1.0.1108.44
Framework
WinUI2/UWP
Operating System
Windows 10, Windows 11
OS Version
10.0.19045,10.0.26200
Repro steps
Primary repro — standalone probe (no original host needed)
Attached MinesweeperWebViewProbe.zip: a minimal native C++/CX UWP app (UWP AppContainer + WebView2 SDK) that IAT-hooks PostMessageW and counts 0x401.
- Extract the zip, double-click
RunProbe.cmd (approve the UAC prompt).
- Wait ~60 seconds.
- Open
probe_report\Report.txt → read the VERDICT line: HIT = 0x401 growing at ~110–165/s.
Works on any machine with WebView2 Runtime build ≥ 1108 (the script auto-installs/updates the Evergreen runtime only when the runtime is missing or older than build 1108, and reverts all system changes afterwards).
Background — natural repro in the original host (Microsoft Minesweeper, UWP)
Play normally for ~5–40 minutes; msedgewebview2.exe count and system RAM grow until the machine freezes.
Cross-machine probe results (60 s sampling, all HIT)
| Machine |
OS |
Runtime |
0x401 rate |
| Dev machine |
Windows 11 26200 |
151.0.4129.78 |
~165/s |
| Machine A |
Windows 10 19045 |
113.0.1774.50 |
~110/s |
| Machine B |
Windows 10 19045 |
151.0.4129.78 |
~141/s |
Expected vs actual
Expected: the task notification is deduplicated (at most one pending kMsgHaveWork), as upstream Chromium does.
Actual: the notification is posted unconditionally while the drain runs, creating a self-perpetuating message storm that leaks handles and explodes the renderer process tree.
Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
No, this never worked
Last working version (if regression)
No response
What happened?
Summary
In UWP/AppContainer hosts,
EmbeddedBrowserWebView.dll(WebView2 Runtime) notifies its UI thread of queued work by postingPostMessageW(hwnd, 0x401, 0, 0)(0x401=WM_USER+1= ChromiumkMsgHaveWork). The posting site (RVA0xE0E0C) has no CAS deduplication, so while producers (AppTaskRunner::PostTask) keep enqueueing during the drain, the drain re-posts on exit and the loop becomes self-sustaining at ~100–165 msgs/sec.Each pass leaks kernel handles (Event ×27 / Section ×31). Handle growth itself consumes no significant memory — the memory impact is indirect: sustained handle growth makes renderers crash and WebView2 restarts them, until 400–717
msedgewebview2.exeprocesses exhaust free RAM (~98%) and freeze the machine. In contrast, during the 60 s probe run the handle count grows at the same rate while free RAM stays essentially flat — confirming the memory drain comes from the renderer process explosion, not from the handles themselves.MinesweeperWebViewProbe.zip
Root cause: the missing CAS dedup at
0xE0E0C(point A) lets the task notification loop self-perpetuate. Proven by patch: memory-patching0xE0E0C(call→mov eax,1) stops0x401completely, the process count stops growing and a 5-minute handle sample is completely stable — single root cause, no independent second leak. This is an SDK-level defect, not app-specific (HIT was reproduced on Windows 10/11 × Runtime 113/151 with a clean-room probe). Detailed analysis in the collapsible section below.Detailed root-cause analysis (disassembly evidence) — click to expand
Mechanism (static + dynamic)
Comparison with upstream Chromium (
base/message_loop/message_pump_win.cc)kMsgHaveWork = WM_USER + 1— match (0x401)native_msg_scheduled_CAS dedup before posting — present at point B (0x3962F9, silent); absent at point AMessagePumpForIO::ScheduleWork()also CAS-dedups — every upstreamkMsgHaveWorkposter is protected; point A has no equivalentDynamic counters (WinDbg, 1 min) — point A
0xE0E0C: 837 | point B0x3962F9: 0 | normal-play baseline: 6,109/min (~102/s)Causal proof (patch of point A, 1 min) —
PostMessageW0x401 counter grew by just +1 in the minute after the patch — a real stop, not a slowdown (the storm normally runs at hundreds of posts/min, so +1 means it fully ceased) | process count: growing → stable | 5-min handle sample: completely stableSelf-feeding ratio (per-thread PostTask, 1 min) — UI thread (0x401 chain): 40,570 (99.4%) | other threads: 242 (0.6%)
Impact — resource-exhaustion DoS (system freeze), not memory corruption, no sandbox escape.
Related: #5290 — crash in EmbeddedBrowserWebView with
TaskRunner::PostTaskon the stack; different symptom (abort crash vs memory-exhaustion process explosion) but likely the same AppTaskRunner task-dispatch subsystem.Importance
Important. My app's user experience is significantly compromised.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
151.0.4129.78
SDK Version
1.0.1108.44
Framework
WinUI2/UWP
Operating System
Windows 10, Windows 11
OS Version
10.0.19045,10.0.26200
Repro steps
Primary repro — standalone probe (no original host needed)
Attached
MinesweeperWebViewProbe.zip: a minimal native C++/CX UWP app (UWP AppContainer + WebView2 SDK) that IAT-hooksPostMessageWand counts0x401.RunProbe.cmd(approve the UAC prompt).probe_report\Report.txt→ read theVERDICTline: HIT = 0x401 growing at ~110–165/s.Works on any machine with WebView2 Runtime build ≥ 1108 (the script auto-installs/updates the Evergreen runtime only when the runtime is missing or older than build 1108, and reverts all system changes afterwards).
Background — natural repro in the original host (Microsoft Minesweeper, UWP)
Play normally for ~5–40 minutes;
msedgewebview2.execount and system RAM grow until the machine freezes.Cross-machine probe results (60 s sampling, all HIT)
Expected vs actual
Expected: the task notification is deduplicated (at most one pending
kMsgHaveWork), as upstream Chromium does.Actual: the notification is posted unconditionally while the drain runs, creating a self-perpetuating message storm that leaks handles and explodes the renderer process tree.
Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
No, this never worked
Last working version (if regression)
No response