MicrosoftEdge / MicrosoftEdge/WebView2Feedback
[Problem/Bug]: WebView2 UWP (EmbeddedBrowserWebView.dll) self-perpetuating 0x401/WM_USER+1 message loop -> handle leak -> renderer process explosion
Nobody has claimed this yet.
- Dominant language
- PowerShell
- Stars
- 526
- Forks
- 67
- PR merge metrics
- No merged PRs in 30d
Description
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.
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)
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 equivalent- Design intent: "at most one kMsgHaveWork message is EVER pending" — point A is exactly where this protection is missing
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 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.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
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the attached MinesweeperWebViewProbe.zip and run RunProbe.cmd, then inspect probe_report/Report.txt and the 0x401 counters described in the issue. Compare the notification behavior with Chromium's base/message_loop/message_pump_win.cc; done means the 0x401 storm, renderer process growth, and handle growth no longer occur under the probe.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- desktop, operating-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100