[windows] fix memory leak in WebView#18810
Merged
jonathanpeppers merged 1 commit intodotnet:mainfrom Nov 20, 2023
Merged
Conversation
Context: dotnet#18365 Context: https://github.com/heyThorsten/GCTest Testing the sample app, I could see a leak in `WebView` on Windows. A memory snapshot showed: Microsoft.Maui.Handlers.WebViewHandler Windows.Foundation.TypedEventHandler<Microsoft.UI.Xaml.Controls.WebView2, Microsoft.UI.Xaml.Controls.CoreWebView2InitializedEventArgs> WinRT._EventSource_global__Windows_Foundation_TypedEventHandler_global__Microsoft_UI_Xaml_Controls_WebView2__global__Microsoft_UI_Xaml_Controls_CoreWebView2InitializedEventArgs_+EventState Windows.Foundation.TypedEventHandler<Microsoft.UI.Xaml.Controls.WebView2, Microsoft.UI.Xaml.Controls.CoreWebView2InitializedEventArgs> [Dependent Handle, Microsoft.Maui.Platform.LayoutPanel <0x2079E7A8D00>] Microsoft.UI.Xaml.RoutedEventHandler WinRT._EventSource_global__Microsoft_UI_Xaml_RoutedEventHandler+EventState Microsoft.UI.Xaml.RoutedEventHandler [Dependent Handle, Microsoft.Maui.Platform.LayoutPanel <0x2079E7A8D00>] I could this same leak in `WebView` by updating `MemoryTests` to do: if (view is WebView webView) { webView.Source = new HtmlWebViewSource { Html = "<p>hi</p>" }; await Task.Delay(1000); } After a bit of debugging, I found that events on `WebView` seem to suffer from the same "circular reference" problem we see on iOS. This makes sense, as it is an unmanaged/native control. (Might be COM?) So we have the cycle: * `WebViewHandler` -> * `WebView2` -> * Various `WebView2` events: * `CoreWebView2Initialized` * `HistoryChanged` * `NavigationStarting` * `NavigationCompleted` * `WebViewHandler` Using the same pattern we've been using for iOS: creating a `WebView2Proxy` type solves the issue. Note that I didn't have to do this for all events, just the ones subscribing to `WebView2`-related events. I also don't see the `WebView2Proxy` object living forever, so the issue does appear to be a cycle.
21 tasks
rmarinho
reviewed
Nov 17, 2023
| protected override void ConnectHandler(WebView2 platformView) | ||
| { | ||
| platformView.CoreWebView2Initialized += OnCoreWebView2Initialized; | ||
| _proxy.Connect(this, platformView); |
Member
There was a problem hiding this comment.
Hum shouldn't we just connect the proxy when WebView2 is initialized? I think we need this I remember other bug related with this where there was an exception related with this. @Eilon do you remember ?
Member
Author
There was a problem hiding this comment.
The connect method should be the same as what it was doing before:
public void Connect(WebViewHandler handler, WebView2 platformView)
{
_handler = new(handler);
platformView.CoreWebView2Initialized += OnCoreWebView2Initialized;
}I don't think I changed any events -- just moved methods to a new class.
Contributor
There was a problem hiding this comment.
@rmarinho hmm sorry I don't specifically remember a bug around this, but maybe there was.
rmarinho
approved these changes
Nov 17, 2023
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context: #18365
Context: https://github.com/heyThorsten/GCTest
Testing the sample app, I could see a leak in
WebViewon Windows. A memory snapshot showed:I could this same leak in
WebViewby updatingMemoryTeststo do:After a bit of debugging, I found that events on
WebViewseem to suffer from the same "circular reference" problem we see on iOS. This makes sense, as it is an unmanaged/native control. (Might be COM?)So we have the cycle:
WebViewHandler->WebView2->WebView2events:CoreWebView2InitializedHistoryChangedNavigationStartingNavigationCompletedWebViewHandlerUsing the same pattern we've been using for iOS: creating a
WebView2Proxytype solves the issue. Note that I didn't have to do this for all events, just the ones subscribing toWebView2-related events. I also don't see theWebView2Proxyobject living forever, so the issue does appear to be a cycle.