Skip to content

fix(runtime-wry): add response channel to CreateWindow for HWND readiness#14915

Open
npiesco wants to merge 1 commit intotauri-apps:devfrom
npiesco:fix/deferred-webview2-creation
Open

fix(runtime-wry): add response channel to CreateWindow for HWND readiness#14915
npiesco wants to merge 1 commit intotauri-apps:devfrom
npiesco:fix/deferred-webview2-creation

Conversation

@npiesco
Copy link

@npiesco npiesco commented Feb 8, 2026

Summary

Adds a Sender<Result<()>> to Message::CreateWindow so the caller blocks until the window's HWND is registered on the event loop thread, fixing a race condition where create_window returned before the window was usable.

Closes #14914. Related: tauri-apps/wry#1665, tauri-apps/wry#1666.

Problem

create_window sends a Message::CreateWindow to the event loop via the proxy and returns immediately. The event loop thread then creates the window, registers the HWND in the window map, and installs WebView2 but the caller has already returned from build() and may attempt to use .hwnd() or other window methods before the HWND is available.

This race was discovered while fixing the ARM64 WebView2 deadlock (tauri-apps/wry#1665): even after fixing the wry-level deadlock, the Tauri runtime would intermittently fail because create_window returned a WebviewWindow whose HWND wasn't yet registered.

On x86/x64 the race window is small enough that it rarely triggers, but on ARM64 (Snapdragon X Elite) the different timing makes it deterministic.

Solution

Add a oneshot Sender<Result<()>> to the Message::CreateWindow variant:

  1. Caller side (create_window): Creates a std::sync::mpsc::channel(), attaches the sender to the message, sends it to the event loop, then blocks on rx.recv() until the event loop confirms completion.
  2. Handler side (event loop Message::CreateWindow match arm): After the window is created and registered in the window map, sends Ok(()) through the channel. On error, sends Err(...).

This ensures build() does not return until the HWND is registered and ready.

Testing

  • 4 unit tests added:
    • create_window_message_carries_sender verifies the Sender is included in the message variant
    • create_window_response_channel_success verifies Ok(()) flows through the channel
    • create_window_response_channel_error verifies errors propagate
    • create_window_response_channel_blocks_caller verifies the caller blocks until the handler responds
  • cargo test -p tauri-runtime-wry passes (4 passed, 0 failed)
  • cargo clippy -p tauri-runtime-wry clean (0 warnings)
  • Tested on Windows ARM64 (Snapdragon X Elite) race condition resolved
  • Tested on WSL2/Linux zero regressions

Minimal Reproduction

https://github.com/npiesco/wry-arm64-deadlock

Dependency

This fix is independent of tauri-apps/wry#1666 (the CoWaitForMultipleHandles fix), but both are needed together to fully resolve the ARM64 deadlock + HWND race. They can be merged in either order.

…ness

Message::CreateWindow was fire-and-forget: send_user_message dispatched the creation request to the event loop thread and returned immediately. On Windows, downstream code that called hwnd() could race against the event loop inserting the window into the window map.

Add a Sender<Result<()>> to Message::CreateWindow. The event loop handler now signals Ok(()) after inserting the window, and the caller blocks on the receiver, guaranteeing the HWND exists before create_window returns.

Includes 4 unit tests for the response channel contract: success propagation, error propagation, blocking semantics, and compile-time type assertion.

Ref: https://github.com/npiesco/wry-arm64-deadlock (minimal reproduction)
@npiesco npiesco requested a review from a team as a code owner February 8, 2026 17:57
@github-project-automation github-project-automation bot moved this to 📬Proposal in Roadmap Feb 8, 2026
@Legend-Master Legend-Master added the ai-slop Low effort content, see https://github.com/tauri-apps/tauri?tab=contributing-ov-file#ai-tool-policy label Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-slop Low effort content, see https://github.com/tauri-apps/tauri?tab=contributing-ov-file#ai-tool-policy

Projects

Status: 📬Proposal

Development

Successfully merging this pull request may close these issues.

[bug] create_window race condition: HWND not registered before function returns

2 participants