Describe the bug
Windows ARM64 (tested on my Snapdragon X Elite / aarch64-pc-windows-msvc), creating second WebView2 controller from main STA thread deadlocks inside MsgWaitForMultipleObjectsEx. Completion callback for CreateCoreWebView2Controlleris never delivered because nestedGetMessage/PeekMessageloop inwebview2_com::wait_with_pump` prevents COM from re-entering apartment.
This is root cause behind issue #583 (deadlock creating new window from IPC handler). #583 was worked around by creating windows outside handlers, underlying problem remains: mpsc::channel + wait_with_pump pattern uses nested Win32 message pump that does not allow COM STA re-entrancy.
Root Cause
wait_with_pump calls MsgWaitForMultipleObjectsEx + PeekMessage/DispatchMessage in a loop. This is a Win32-level message pump, not COM-level one. COM's STA requires that apartment's message filter processes incoming COM calls raw GetMessage loop does not do this. On x86/x64, this happens to work most of the time because WebView2's internal RPC dispatch piggybacks on window messages. On ARM64, timing/threading model exposes bug deterministically.
Fix
Replace mpsc::channel + wait_with_pump with CoWaitForMultipleHandles using COWAIT_DISPATCH_CALLS | COWAIT_DISPATCH_WINDOW_MESSAGES. This is COM-sanctioned mechanism for yielding an STA thread:
- Dispatches COM calls (re-entrancy) required for WebView2 async completion callbacks
- Dispatches window messages required for event loop to stay responsive
- Works on all architectures
Consistent with Microsoft's WebView2 threading model documentation on reentrancy.
Affected call sites
create_environment() CreateCoreWebView2EnvironmentWithOptions
create_controller() CreateCoreWebView2Controller / CreateCoreWebView2ControllerWithOptions
cookies_inner() CookieManager().GetCookies
Minimal Reproduction
https://github.com/npiesco/wry-arm64-deadlock
main branch: deadlocks on ARM64 (uses upstream wry)
fix/vendored-wry-tauri branch: works (uses patched wry fork)
Expected behavior
WebView2 environment and controller creation should complete without deadlocking on all architectures.
Platform and Versions
- OS: Windows 11 ARM64 (Snapdragon X Elite)
- Rustc: 1.87.0 (aarch64-pc-windows-msvc)
- wry: 0.54.1
Related
Describe the bug
Windows ARM64 (tested on my Snapdragon X Elite /
aarch64-pc-windows-msvc), creating secondWebView2controller from main STA thread deadlocks insideMsgWaitForMultipleObjectsEx. Completion callback for CreateCoreWebView2Controlleris never delivered because nestedGetMessage/PeekMessageloop inwebview2_com::wait_with_pump` prevents COM from re-entering apartment.This is root cause behind issue #583 (deadlock creating new window from IPC handler). #583 was worked around by creating windows outside handlers, underlying problem remains:
mpsc::channel+wait_with_pumppattern uses nested Win32 message pump that does not allow COM STA re-entrancy.Root Cause
wait_with_pumpcallsMsgWaitForMultipleObjectsEx+PeekMessage/DispatchMessagein a loop. This is a Win32-level message pump, not COM-level one. COM's STA requires that apartment's message filter processes incoming COM calls rawGetMessageloop does not do this. On x86/x64, this happens to work most of the time because WebView2's internal RPC dispatch piggybacks on window messages. On ARM64, timing/threading model exposes bug deterministically.Fix
Replace
mpsc::channel+wait_with_pumpwithCoWaitForMultipleHandlesusingCOWAIT_DISPATCH_CALLS | COWAIT_DISPATCH_WINDOW_MESSAGES. This is COM-sanctioned mechanism for yielding an STA thread:Consistent with Microsoft's WebView2 threading model documentation on reentrancy.
Affected call sites
create_environment()CreateCoreWebView2EnvironmentWithOptionscreate_controller()CreateCoreWebView2Controller/CreateCoreWebView2ControllerWithOptionscookies_inner()CookieManager().GetCookiesMinimal Reproduction
https://github.com/npiesco/wry-arm64-deadlock
mainbranch: deadlocks on ARM64 (uses upstream wry)fix/vendored-wry-tauribranch: works (uses patched wry fork)Expected behavior
WebView2 environment and controller creation should complete without deadlocking on all architectures.
Platform and Versions
Related