Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browser process crash in idle mode #4141

Open
sg-cd opened this issue Nov 8, 2023 · 7 comments
Open

Browser process crash in idle mode #4141

sg-cd opened this issue Nov 8, 2023 · 7 comments
Assignees
Labels
bug Something isn't working

Comments

@sg-cd
Copy link

sg-cd commented Nov 8, 2023

What happened?

We have Edge Webview2 integrated in our Windows desktop app, and on receiving the CoreWebView2Environment.NewBrowserVersionAvailable event, we recreate the CoreWebView2Environment and WebView2 instances.
This has been working fine for us for more than a year, but recently we observed the issue on 2 systems that the NewBrowserVersionAvailable event is getting raised while the laptop is in an idle mode.

  • The laptop was locked and left idle overnight, but it appears it did not go to sleep, since we did not get the SystemEvents.PowerModeChanged with PowerModes.Suspend. But from our logs it appears to be running code at reduced frequency since there are gaps of few hours in between.

  • While in this mode, we got the NewBrowserVersionAvailable. CoreWebView2Environment.CreateAsync() completed successfully, and we proceeded with the Webview2 creation. But WebView2.CoreWebView2InitializationCompleted event was received after 1 hour, and then we got the exception "The WebView control is no longer valid because the browser process crashed.To work around this, please listen for the CoreWebView2.ProcessFailed event to explicitly manage the lifetime of the WebView2 control in the event of a browser failure.https://docs.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2.processfailed"

  • We do not have the process dump available.

  • Note: On running the command "powercfg -waketimers" on the laptop, we got the message "There are no active wake timers in the system.".

  • Is this something that can be fixed from Edge Webview2, or is there any event we can listen to which would indicate this kind of idle mode?

Importance

Important. My app's user experience is significantly compromised.

Runtime Channel

Stable release (WebView2 Runtime)

Runtime Version

117.0.2045.47

SDK Version

No response

Framework

WPF

Operating System

Windows 10

OS Version

Build 19044

Repro steps

On receiving the CoreWebView2Environment.NewBrowserVersionAvailable event in idle mode, recreate the CoreWebView2Environment and WebView2 instances.
Expected: CoreWebView2Environment and Webview2 should be initialized successfully.
Observed: Delayed Webview2 initialization, and then crash.

Regression

Don't know

Last working version (if regression)

No response

@sg-cd sg-cd added the bug Something isn't working label Nov 8, 2023
@sg-cd
Copy link
Author

sg-cd commented Nov 14, 2023

Any update on this?

@victorhuangwq
Copy link
Collaborator

I think @LiangTheDev might have a better idea. Could you help take a look at this?

@LiangTheDev
Copy link
Member

From what you described, it seems that something happened in the environment where the app and WebView2 are running. We don't really have expertise on this.
However, to mitigate the impact, you could listen to CoreWebView2.ProcessFailed event, log CoreWebView2ProcessFailedEventArgs.ExitCode and collect potential dump files of the crash, and then recreate WebView2 environment and WebView2.
Once we have a crash dump file, we would know more on cause and potential mitigation.

@sg-cd
Copy link
Author

sg-cd commented Nov 15, 2023

We do listen to CoreWebView2.ProcessFailed event. It did not get triggered in this case or crashed before we could subscribe to it, indicating the crash possibly happened in WebView2.EnsureCoreWebView2Async(). (From the documentation for EnsureCoreWebView2Async(): "When the task completes then the Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2 property will be available for use (i.e. non-null). Note that the control's Microsoft.Web.WebView2.Wpf.WebView2.CoreWebView2InitializationCompleted event will be invoked before the task completes.")

@LiangTheDev
Copy link
Member

Got it. Some thoughts/clarifications:

After receiving NewBrowserVersionAvailable, I assume that we are closing/disposing the old WebView2 instance before trying to recreate new one. Have we wait for Environment.BrowserProcessExited event before recreating new instance? If not, there could be a race condition where closing the old instance causing the related WebView2 browser process to shutdown while the request to create the new instance is routed to it as it is still running, and then the shutdown continues and we got browser process exited event for the new WebView2 creation. Waiting for Environment.BrowserProcessExited could avoid this race condition.

When CoreWebView2InitializationCompleted event is invoked, is CoreWebView2InitializationCompletedEventArgs.IsSuccess true or false, if false, what is the InitializationException value?

Are we listen to CoreWebView2.ProcessFailed event right in the CoreWebView2InitializationCompleted event handler, or right after await EnsureCoreWebView2Async()?
Inside CoreWebView2InitializationCompleted event handler, CoreWebView2 object should still be valid. If it is not, this is something we could improve in WebView2 code.
After await EnsureCoreWebView2Async(), it is possible that we detected browser process failed between WebView initialization completed and the await result is dispatched. If this is the case, it would be hard for WebView2 code to do anything. This could be mitigated by putting CoreWebView2.ProcessFailed event handler registration also under try-catch, or switch to use CoreWebView2InitializationCompleted event handler to register CoreWebView2.ProcessFailed event handler.

@sg-cd
Copy link
Author

sg-cd commented Nov 16, 2023

  • Yes, on receiving NewBrowserVersionAvailable, we dispose the old WebView2 instance. Then on receiving Environment.BrowserProcessExited event, we recreate new instance.
  • CoreWebView2InitializationCompleted event was invoked with CoreWebView2InitializationCompletedEventArgs.IsSuccess as true, and InitializationException as null.
  • We do not listen to CoreWebView2.ProcessFailed event in the CoreWebView2InitializationCompleted event handler, since documentation for EnsureCoreWebView2Async() says that CoreWebView2 will be non-null only after its task completion: "When the task completes then the CoreWebView2 property will be available for use (i.e. non-null). Note that the control's CoreWebView2InitializationCompleted event will be invoked before the task completes."
  • For same reason as above, we would not be able to put EnsureCoreWebView2Async() and CoreWebView2.ProcessFailed registration in try-catch, right?
  • Currently, after await EnsureCoreWebView2Async() we set a few properties of CoreWebView2.Settings (like AreDevToolsEnabled, IsStatusBarEnabled, etc.) before ProcessFailed registration. We can move the registration above, but if Webview2 creation/initialization is failing due to system being in "idle" mode, I presume we would run into the same problem again on retrying.

@LiangTheDev
Copy link
Member

As you stated that there were 2 incidences of this, it might not happen 100% on the device. We would know better when we have more info like process exit code and dumps. Retrying would be better to crashing the app.

Looks like we are hit exception accessing CoreWebView2 objects right after await EnsureCoreWebView2Async(), and it should be the race condition that I was thinking about. The documentation needs updating. Normally, it is very unlikely that browser process could be gone between we complete a task and the completions is dispatched. But it seemed that in this slowed down environment, it could happen.

So, as a mitigation, you could put the code accessing CoreWebView2 objects after await EnsureCoreWebView2Async up to ProcessFailed registration under the try-catch, and treat exceptions as WebView creation failure, and retry creating a new instance. FWIW, you can put any code under try-catch if whether the WebView2 objects are in good status or not, if they are in good status, no exception will be thrown and everything is normal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants