MicrosoftEdge / WebView2Feedback

Feedback and discussions about Microsoft Edge WebView2
https://aka.ms/webview2
423 stars 51 forks source link

[Problem/Bug]: Stability regression: v125 and up regularly crashing on select sites #4602

Open RendijsSmukulis opened 1 month ago

RendijsSmukulis commented 1 month ago

What happened?

WebView2 - Break instruction exception: null
  Module "ntdll!RtlUserThreadStart+0x28"
  Module "kernel32!BaseThreadInitThunk+0x1d"
  Module "msedgewebview2!__scrt_common_main_seh+0x106"
  Module "msedgewebview2!wWinMain+0x40d"
  Module "msedgewebview2!MainDllLoader::Launch+0x373"
  Module "msedge!ChromeMain+0x2c5"
  Module "msedge!ChromeMain+0x971"
  Module "msedge!ChromeMain+0x14c1"
  Module "msedge!ChromeMain+0x1bc9"
  Module "msedge!ChromeMain+0x101e0"
  Module "msedge!ChromeMain+0x10c8a"
  Module "msedge!ChromeMain+0x117a2"
  Module "msedge!IsSandboxedProcess+0x262bf02"
  Module "msedge!IsSandboxedProcess+0x1783851"
  Module "msedge!IsSandboxedProcess+0x1a2e218"
  Module "msedge!RelaunchChromeBrowserWithNewCommandLineIfNeeded+0x5e8d11"
  Module "msedge!RelaunchChromeBrowserWithNewCommandLineIfNeeded+0x3bb68f"
  Module "msedge!RelaunchChromeBrowserWithNewCommandLineIfNeeded+0x3bc702"
  Module "msedge!RelaunchChromeBrowserWithNewCommandLineIfNeeded+0x3bd06a"
  Module "msedge!IsSandboxedProcess+0x960a9"
  Module "msedge!IsSandboxedProcess+0xe3988"
  Module "msedge!IsSandboxedProcess+0x940e5"
  Module "msedge!IsSandboxedProcess+0x15bc41a"
  Module "msedge!CrashForExceptionInNonABICompliantCodeRange+0x566dc8"

Importance

Blocking. My app's basic functions are not working due to this issue.

Runtime Channel

Stable release (WebView2 Runtime), Prerelease (Edge Canary/Dev/Beta)

Runtime Version

125.0.2535.79

SDK Version

1.0.2535.41

Framework

WPF

Operating System

Windows 10, Windows 11

OS Version

No response

Repro steps

The crashes seen in the vanilla WPF app were different from the ones seen in our app. Currently working on a minimal repro for this exact crash. Dumps from our app will be sent to Microsoft email.

Repros in Edge Browser

No, issue does not reproduce in the corresponding Edge version

Regression

Regression in newer Runtime

Last working version (if regression)

124

AB#51481141

vbryh-msft commented 1 month ago

Thank you for reporting the issue. Could you please attach dump file or send it to email

MarkIngramUK commented 1 month ago

@vbryh-msft , will email it to you (I've already sent it over to @nishitha-burman, @aluhrs13 & @liminzhu )

RendijsSmukulis commented 1 month ago

We now have a minimal repro for this. In short - this is caused by some change in v125 onwards, which has impacted the stability of cross-origin request handling through the Fetch CDP API. I.e. when doing this pattern:

  Target.enable()
  Target.setDiscoverTargets(...)
  Target.setAutoAttach(autoAttach=T, waitForDebuggerOnStart=T, flatten=T)
  // call Fetch.enable() to enable network request handling on new targets (e.g. iframes to different origin), then runIfWaitingForDebugger to resume said target.
  Fetch.enable()
  Runtime.runIfWaitingForDebugger()

Minimal repro attached, just scroll around Temu a bit for a crash:

MainWindow.xaml

<Window x:Class="WebView2Wpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WebView2Wpf"
        xmlns:wpf="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
            <TextBox Name="urlToNavTo" HorizontalAlignment="Stretch" Width="300"/>
            <Button Name="Button" Click="Button_OnClick">go</Button>
        </StackPanel>
        <wpf:WebView2 Name="webview" Grid.Row="1" />
    </Grid>
</Window>

MainWindow.xaml.cs

using Microsoft.Web.WebView2.Core;
using System;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows;

namespace WebView2Wpf
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.webview.CoreWebView2InitializationCompleted += WebviewOnCoreWebView2InitializationCompleted;

            var options = new CoreWebView2EnvironmentOptions();
            var e = CoreWebView2Environment.CreateAsync(options: options).Result;
            this.webview.EnsureCoreWebView2Async(e);
        }

        private async void WebviewOnCoreWebView2InitializationCompleted(object? sender, CoreWebView2InitializationCompletedEventArgs e)
        {
            await webview.CoreWebView2.CallDevToolsProtocolMethodAsync("Target.setDiscoverTargets", "{\"discover\":true}");
            webview.CoreWebView2.GetDevToolsProtocolEventReceiver("Target.attachedToTarget").DevToolsProtocolEventReceived += OnAttachedToTarget;

            var autoAttachParams = JsonSerializer.Serialize(
                new SetAutoAttachParameters
                {
                    WaitForDebuggerOnStart = true,
                    Flatten = true,
                    AutoAttach = true
                }
            );

            await webview.CoreWebView2.CallDevToolsProtocolMethodAsync("Target.setAutoAttach", autoAttachParams);
            webview.CoreWebView2.GetDevToolsProtocolEventReceiver("Fetch.requestPaused").DevToolsProtocolEventReceived += OnRequestPaused;

            this.webview.CoreWebView2.Navigate("https://temu.com");
            this.webview.CoreWebView2.NavigationCompleted += CoreWebView2OnNavigationCompleted;
        }

        private async void OnRequestPaused(object? sender, CoreWebView2DevToolsProtocolEventReceivedEventArgs e)
        {
            try
            {
                var req = JsonSerializer.Deserialize<RequestIdWrapper>(e.ParameterObjectAsJson);

                var resp = JsonSerializer.Serialize(new RequestIdWrapper
                {
                    RequestId = req.RequestId
                });

                Debug.WriteLine($"+++> req handled: {resp}");
                await this.webview.CoreWebView2.CallDevToolsProtocolMethodForSessionAsync(e.SessionId, "Fetch.continueRequest", resp);
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"+++> Failed handling: {ex}");
            }
        }

        private async void OnAttachedToTarget(object? sender, CoreWebView2DevToolsProtocolEventReceivedEventArgs e)
        {
            var attachedSession = JsonSerializer.Deserialize<AutoAttachedSession>(e.ParameterObjectAsJson);
            var sessionId = attachedSession.SessionId;

            Debug.WriteLine($"+++> Attached to target: {e.ParameterObjectAsJson}");

            await webview.CoreWebView2.CallDevToolsProtocolMethodForSessionAsync(sessionId, "Fetch.enable", "{\"patterns\":[{\"requestStage\":\"Request\"}]}");
            await webview.CoreWebView2.CallDevToolsProtocolMethodForSessionAsync(sessionId, "Runtime.runIfWaitingForDebugger", "{}");

            Debug.WriteLine($"+++> Fetch enabled");
        }

        private void CoreWebView2OnNavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
        {
            this.urlToNavTo.Text = this.webview.Source.OriginalString;
        }

        private void Button_OnClick(object sender, RoutedEventArgs e)
        {
            this.webview.CoreWebView2.Navigate(this.urlToNavTo.Text);
        }

        public record SetAutoAttachParameters
        {
            [JsonPropertyName("autoAttach")]
            public bool AutoAttach { get; init; }

            [JsonPropertyName("waitForDebuggerOnStart")]
            public bool WaitForDebuggerOnStart { get; init; }

            [JsonPropertyName("flatten")]
            [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
            public bool? Flatten { get; init; }
        }

        public record RequestIdWrapper
        {
            [JsonPropertyName("requestId")]
            public string RequestId { get; init; }
        }

        public record AutoAttachedSession
        {
            [JsonPropertyName("sessionId")]
            public string SessionId { get; init; }

            [JsonPropertyName("targetInfo")]
            public TargetInfo TargetInfo { get; init; }

            [JsonPropertyName("waitingForDebugger")]
            public bool WaitingForDebugger { get; init; }
        }

        public record TargetInfo
        {
            [JsonPropertyName("attached")]
            public bool Attached { get; init; }

            [JsonPropertyName("browserContextId")]
            public string BrowserContextId { get; init; }

            [JsonPropertyName("canAccessOpener")]
            public bool CanAccessOpener { get; init; }

            [JsonPropertyName("targetId")]
            public string TargetId { get; init; }

            [JsonPropertyName("title")]
            public string Title { get; init; }

            [JsonPropertyName("type")]
            public string Type { get; init; }

            [JsonPropertyName("url")]
            public string Url { get; init; }
        }
    }
}
RendijsSmukulis commented 1 month ago

NB: This crash is also happening when using the WebView2's network request APIs, no need for CDP:

        private void WebviewOnCoreWebView2InitializationCompleted(object? sender, CoreWebView2InitializationCompletedEventArgs e)
        {
            this.webview.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All, CoreWebView2WebResourceRequestSourceKinds.All);
            this.webview.CoreWebView2.WebResourceRequested += CoreWebView2OnWebResourceRequested;
            this.webview.CoreWebView2.Navigate("https://temu.com");
        }

Edit: from additional debugging, it appears to be caused specifically by service_worker targets - might help you with finding the root cause.

seldoff commented 4 days ago

I feel like this Chromium bug is directly related to this issue. Considering that someone from Microsoft has filed it, do you have any updates or insight on the issue?

peiche-jessica commented 4 days ago

Hi @seldoff, yes it is related to that Chromium bug. We suspect it's related to the Fetch.requestPaused but we're also seeking insight from Chromium. We will share more when we know more. Thanks!

seldoff commented 4 days ago

@peiche-jessica, I'm pretty sure that we have identified the Chromium commit that caused this regression. Please see my comment in the bug tracker.