App crashes when exiting an app that uses MenuBar and WebView2
See original GitHub issueDescribe the bug
In an app that uses MenuBar and WebView2, if you exit the app after performing the following processing, an access violation will occur.
- Call WebView2.EnsureCoreWebView2Async.
- Add WebView2 to the UI.
- Remove WebView2 from the UI after WebView2 is displayed on the screen.
An access violation occurs when the “exit” function is called in “exe_common.inl”.
This issue only occurs in Windows App SDK 1.1.X and not in 1.0.3.
Steps to reproduce the bug
This problem is reproduced with a very simple code.
- Create a “Blank App, Packaged (WinUI 3 in Desktop)” project in Visual Studio. (Project name: App1)
- Update the Windows App SDK to version 1.1.0 or higher with Nuget Package Manager.
- Edit code
MainWindow.xaml
<Window
x:Class="App1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<MenuBar Grid.Row="0">
<MenuBar.Items>
<MenuBarItem Title="File">
<MenuBarItem.Items>
<MenuFlyoutItem Text="Open" Click="OpenButtonClick" />
</MenuBarItem.Items>
</MenuBarItem>
</MenuBar.Items>
</MenuBar>
<Grid x:Name="Holder" Grid.Row="1" />
</Grid>
</Window>
MainWindow.idl
namespace App1
{
[default_interface]
runtimeclass MainWindow : Microsoft.UI.Xaml.Window
{
MainWindow();
}
}
MainWindow.xaml.h
#pragma once
#include "MainWindow.g.h"
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::UI::Xaml;
using namespace winrt::Microsoft::UI::Xaml::Controls;
namespace winrt::App1::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
MainWindow();
void OpenButtonClick(IInspectable const& sender, RoutedEventArgs const& e);
IAsyncAction ShowWebsite(WebView2 web);
};
}
namespace winrt::App1::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}
MainWindow.xaml.cpp
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
#include <winrt/Microsoft.Web.WebView2.Core.h>
using namespace winrt::Windows::Foundation;
using namespace winrt::Microsoft::UI::Xaml;
using namespace winrt::Microsoft::UI::Xaml::Controls;
using namespace winrt::Microsoft::Web::WebView2::Core;
namespace winrt::App1::implementation
{
MainWindow::MainWindow()
{
InitializeComponent();
}
void MainWindow::OpenButtonClick(IInspectable const& sender, RoutedEventArgs const& e) {
Holder().Children().Clear();
WebView2 web{};
ShowWebsite(web);
Holder().Children().Append(web);
}
IAsyncAction MainWindow::ShowWebsite(WebView2 web)
{
co_await web.EnsureCoreWebView2Async();
auto core = web.CoreWebView2();
core.Navigate(L"https://www.microsoft.com/");
co_return;
}
}
- Start Debugging (Platform: x64)
- Repeat “File”-> “Open” twice from the menu bar.
- Close the main window and exit the app.
- An access violation occurs. (See screenshot)
Expected behavior
No error occurs when exiting the app.
Screenshots
NuGet package version
WinUI 3 - Windows App SDK 1.1.1
Windows app type
- UWP
- Win32
Device form factor
Desktop
Windows version
Windows 10 (21H2): Build 19044
Additional context
This issue does not occur if you edit the code as one of the following:
- Do not remove WebView2 from the UI. (Do not call
Holder().Children().Clear()
.) - Do not call
EnsureCoreWebView2Async
. (Comment out the contents of theShowWebsite
function.) - Replace the menu bar with an “Open” button.
<Button Grid.Row="0" Click="OpenButtonClick">Open</Button>
Issue Analytics
- State:
- Created a year ago
- Comments:8 (3 by maintainers)
Top Results From Across the Web
Power BI Desktop WebView2 crash - Page 2
Windows was trying to restart, said that it was having problems closing Power BI Desktop, clicked Cancel to manually close the apps.
Read more >Webview2 crashes when calling document.write on newly ...
This is a bug in the WebView2 Runtime. It is fixed in versions 101.0.1210.8 and higher. See Test upcoming APIs and features for...
Read more >Overview of WebView2 features and APIs
Communicate between native code and web code using simple messages, JavaScript code, and native objects. Browser features, The WebView2 control ...
Read more >Xaml Islands Win32 MenuFlyoutSubItem crash
Run the app, open the menu, hover over the first SubItem until the menu animation starts playing, then quickly move to the second...
Read more >My app crashes when closing my seccond window
My app crashes when closing my seccond window. This is all I get. No information at all. I am using webview in my...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
The reason behind this crash is calling into threadpoolwinrt.dll when it is already freed.
On process shutdown, dlls are unloaded in reverse order. As threadpoolwinrt.dll is loaded later than Microsoft.Ui.Xaml.dll, it gets unloaded first. During unload, it sets
Microsoft::WRL::Details::ModuleBase::module_
to nullptr.Here’s a stack trace when this happens:
Followed by this,
Microsoft.Ui.Xaml.dll
unloads, releasing its COM references toWindows.System.Threading.ThreadPoolTimer
. Stack trace:However,
Microsoft::WRL::ActivationFactory<Windows::System::Threading::IThreadPoolStatics,Microsoft::WRL::FtmBase,Microsoft::WRL::Details::Nil,0>::Release
tries to callMicrosoft::WRL::Details::ModuleBase::module_->DecrementObjectCount(void)
, but only when the passed object’s reference count is 0 or 1 post-dereference. On the path with 0 (1 pre-decrement), there’s a nullptr check (even though that shouldn’t happen either), however the path with 1 does not have this nullptr check, hence the crash.This means this crash will occur any time there are two or more references to the ThreadPoolTimer interface, opened from dlls that were loaded earlier and destroyed in their destructors. Xaml keeps one on its own by default, while initializing WebView will cause a second reference, therefore fulfilling the requirements for a crash.
I created a simple C++ program and library to recreate this issue in a cleaner environment:
Dll1.cpp
main.cpp
Setting
how_many
to 1 represents normal Xaml levels of incorrectness, while 2 represents the WebView scenario with two offending modules.Unfortunately I couldn’t come up with a simple workaround, so fixing this is mostly on Microsoft.
The most obvious fix would be not calling
ThreadPoolService::ReleaseFactories
if deinitialization happens due to process exiting. In general it is not a good practice anyways.Fix is now available: https://www.nuget.org/packages/Microsoft.WindowsAppSDK/1.2.230118.102