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

Support process singleton with IBrowserProcessHandler.OnAlreadyRunningAppRelaunch callback #4668

Closed
1 task done
Mik4sa opened this issue Jan 9, 2024 · 11 comments
Closed
1 task done
Assignees
Labels
breaking-change upstream These issues require fixing in the Chromium Embedded Framework(CEF) or Chromium.
Milestone

Comments

@Mik4sa
Copy link

Mik4sa commented Jan 9, 2024

Is there an existing issue for this?

  • I have searched both open/closed issues, no issue already exists.

CefSharp Version

120.1.110

Operating System

Windows 11

Architecture

x64

.Net Version

.NET 4.7.2

Implementation

WinForms

Reproduction Steps

Reproducible with CefSharp.MinimalExample since 120.1.110 (cefsharp/CefSharp.MinimalExample@136a65e).
Just launch the application twice.

Expected behavior

A second launch of the application should be possible (without any restrictions).

Actual behavior

A launch of any more instances result in a crash.

This is the output of thedebug.log from the second launch:

[0109/101550.274:ERROR:crashpad_client_win.cc(546)] CreateProcess: Das System kann die angegebene Datei nicht finden. (0x2)
[0109/101550.285:INFO:crash_reporting.cc(216)] Crash reporting enabled for process: browser
[0109/101550.289:WARNING:alloy_browser_main.cc(167)] Unhandled app relaunch; implement CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch.
[0109/101550.289:ERROR:crashpad_client_win.cc(143)] crash server failed to launch, self-terminating

Regression?

This was working with v120.1.80.

Known Workarounds

No known workarounds

Does this problem also occur in the CEF Sample Application

No

Other information

No response

@yngwu
Copy link

yngwu commented Jan 10, 2024

Same here in our WPF application. Debug.log from v120.1.110

0110/102929.043:WARNING:alloy_browser_main.cc(167)] Unhandled app relaunch; implement CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch.
[0110/103024.131:WARNING:alloy_browser_main.cc(167)] Unhandled app relaunch; implement CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch.
[0110/103203.453:WARNING:alloy_browser_main.cc(167)] Unhandled app relaunch; implement CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch

Looks like it's related to the process singleton enabled by default and a virtual function CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch need to be implemented, see chromiumembedded/cef#3615.

https://github.com/chromiumembedded/cef/blob/a097b62b6e048613484e23ca038c4f1b1dd22cd5/libcef/browser/alloy/alloy_browser_main.cc#L167

@amaitland
Copy link
Member

Chromium is designed so only a single process can access a Cache at a time. Multiple processes is not supported. If it worked previously then it was by luck, not design.

This was working with v120.1.80.

The only CefSharp change was to upgrade to a newer CEF version. You can easily compare tags on github v120.1.80...v120.1.110

Reproducible with CefSharp.MinimalExample since 120.1.110 (cefsharp/CefSharp.MinimalExample@136a65e).
Just launch the application twice.

The MinimalExample isn't designed to be run multiple times. It has a fixed CachePath.

A second launch of the application should be possible (without any restrictions).

That's not really something CefSharp has control over. Someone should ask on chromiumembedded/cef#3615 to see if the change in behaviour is expected.

[0109/101550.289:WARNING:alloy_browser_main.cc(167)] Unhandled app relaunch; implement CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch.

We need to add IBrowserProcessHandler.OnAlreadyRunningAppRelaunch we can use this issue to track that work.

@amaitland amaitland added the upstream These issues require fixing in the Chromium Embedded Framework(CEF) or Chromium. label Jan 13, 2024
@amaitland
Copy link
Member

///
/// Implement this method to provide app-specific behavior when an already
/// running app is relaunched with the same CefSettings.root_cache_path value.
/// For example, activate an existing app window or create a new app window.
/// |command_line| will be read-only. Do not keep a reference to
/// |command_line| outside of this method. Return true if the relaunch is
/// handled or false for default relaunch behavior. Default behavior will
/// create a new default styled Chrome window.
///
/// To avoid cache corruption only a single app instance is allowed to run for
/// a given CefSettings.root_cache_path value. On relaunch the app checks a
/// process singleton lock and then forwards the new launch arguments to the
/// already running app process before exiting early. Client apps should
/// therefore check the CefInitialize() return value for early exit before
/// proceeding.
///
/// This method will be called on the browser process UI thread.
///
/*--cef(optional_param=current_directory)--*/
virtual bool OnAlreadyRunningAppRelaunch(
    CefRefPtr<CefCommandLine> command_line,
    const CefString& current_directory) {
  return false;
}

On relaunch the app checks a process singleton lock and then forwards the new launch arguments to the
already running app process before exiting early. Client apps should therefore check the CefInitialize() return value for early exit before proceeding.

As per CEF API doc (from above).

@amaitland amaitland changed the title Crash on parallel launches in "Cef.Initialize" since 120.1.110 (WinForms) Support process singleton with IBrowserProcessHandler.OnAlreadyRunningAppRelaunch callback Jan 13, 2024
@amaitland amaitland self-assigned this Jan 13, 2024
@amaitland amaitland added this to the 120.1.x milestone Jan 13, 2024
@Mik4sa
Copy link
Author

Mik4sa commented Jan 13, 2024

Ok, got it, thanks
Afaik in our main application we do not have a CachePath set (so no cache is written to the disk) and still the application is crashing. Maybe this info is relevant to you too.

@amaitland
Copy link
Member

[0109/101550.289:WARNING:alloy_browser_main.cc(167)] Unhandled app relaunch; implement CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch.

CEF thinks your application has relaunched with a CachePath or RootCachePath identical to another process. RequestContext cache paths would also count.

Afaik in our main application we do not have a CachePath set (so no cache is written to the disk) and still the application is crashing. Maybe this info is relevant to you too.

Load chrome://version in a ChromiumWebBrowser instance within your application to see what CEF thinks your path values are.

Again from a CefSharp point of view the only thing that changed was an upgrade to a newer version of CEF.

If your application doesn't have a cache set then you'll need to raise an issue at https://github.com/chromiumembedded/cef/issues as that would be an upstream bug.

@Mik4sa
Copy link
Author

Mik4sa commented Jan 15, 2024

Ok I see. There is always a root cache path:
image

@Mik4sa
Copy link
Author

Mik4sa commented Jan 15, 2024

@amaitland Is there a function to get the default root cache path?
Or a way to call native functions from them? Like GetDefaultUserDataDirectory? See: https://source.chromium.org/chromium/chromium/src/+/main:chrome/common/chrome_paths_internal.h?q=GetDefaultUserDataDirectory&ss=chromium

@amaitland
Copy link
Member

Client apps should therefore check the CefInitialize() return value for early exit beforeproceeding.

If the second process call to Cef.Initialzie() isn't returning a value (if it's crashing or terminating the process), then someone needs to create an issue at https://github.com/chromiumembedded/cef/issues

@amaitland
Copy link
Member

Looks like CEF is causing an access violation for the second process(CefSharp.MinimalExample.WinForms.net472.exe) call to Cef.Initialize (CefInitialize)

Faulting application name: CefSharp.MinimalExample.WinForms.net472.exe, version: 1.0.0.0, time stamp: 0xb8fa0b28
Faulting module name: libcef.dll, version: 120.2.5.0, time stamp: 0x659c57ab
Exception code: 0x80000003
Fault offset: 0x00000000046d32e7
Faulting process ID: 0x36ac
Faulting application start time: 0x01da4b157e671427
Faulting application path: C:\projects\CefSharp.MinimalExample\CefSharp.MinimalExample.WinForms\bin.net472\Debug\net472\CefSharp.MinimalExample.WinForms.net472.exe
Faulting module path: C:\projects\CefSharp.MinimalExample\CefSharp.MinimalExample.WinForms\bin.net472\Debug\net472\x64\libcef.dll
Report ID: e5039ffe-5121-4f92-9ecf-27fccc4854c4
Faulting package full name: 
Faulting package-relative application ID: 

Someone will need to raise an issue at https://github.com/chromiumembedded/cef/issues

@amaitland
Copy link
Member

Problem reproduces with the CEF sample application, only appears to be a problem when multi threaded message loop is used (the default in CefSharp).

Upstream issue chromiumembedded/cef#3635

You can try integrating CEF into your applications existing message loop to workaround the problem for now. See https://github.com/cefsharp/CefSharp/wiki/General-Usage#multithreadedmessageloop

@amaitland amaitland modified the milestones: 120.1.x, 121.3.x Feb 9, 2024
@amaitland
Copy link
Member

Upstream issue chromiumembedded/cef#3635

The upstream issue has been resolved. If I'm reading the fix correctly the UI Thread will be shutdown if the process singleton detects an already running instance. So the previous behaviour of having multiple application instances running without providing a RootCachePath is no longer supported/possible.

Please customize CefSettings.root_cache_path for your application. Use of the default value may lead to unintended process singleton behavior

CEF will log this message if RootCachePath is not set, you should ensure that at a minimum you set CefSettings.RootCachePath to a unique folder per application to avoid unwanted calls to OnAlreadyRunningAppRelaunch.

OnAlreadyRunningAppRelaunch can be used to achieve the same behaviour as Chromium. (Single process instance with multiple windows within the one process).
If you need multiple instances that are entirely isolated, then you will need to specify a unique RootCachePath for each.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change upstream These issues require fixing in the Chromium Embedded Framework(CEF) or Chromium.
Projects
None yet
Development

No branches or pull requests

3 participants