Trying to use cefclient as a DLL

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Re: Trying to use cefclient as a DLL

Postby robinm2 » Fri Feb 26, 2021 7:55 pm

Now I have another issue when I start a browser window more than once from the main application:

Code: Select all
[0226/225220.283:FATAL:main.cc(283)] Check failed: !is_initialized.


Code: Select all
    libcef.dll!logging::LogMessage::~LogMessage() Line 867   C++
    libcef.dll!logging::LogMessage::~LogMessage() Line 537   C++
    libcef.dll!logging::CheckError::~CheckError() Line 105   C++
    libcef.dll!service_manager::MainInitialize(service_manager::MainParams & params={...}) Line 285   C++
    libcef.dll!CefMainRunner::ContentMainInitialize(const CefMainArgs & args={...}, void * windows_sandbox_info, int * no_sandbox=0x0ef72ca0) Line 391   C++
    libcef.dll!CefMainRunner::Initialize(CefStructBase<CefSettingsTraits> * settings=0x0ef72c98, scoped_refptr<CefApp> application={...}, const CefMainArgs & args={...}, void * windows_sandbox_info=0x00000000, bool * initialized=0x0ef72c90, base::OnceCallback<void ()> context_initialized={...}) Line 234   C++
    libcef.dll!CefContext::Initialize(const CefMainArgs & args={...}, const CefStructBase<CefSettingsTraits> & settings={...}, scoped_refptr<CefApp> application={...}, void * windows_sandbox_info=0x00000000) Line 356   C++
    libcef.dll!CefInitialize(const CefMainArgs & args={...}, const CefStructBase<CefSettingsTraits> & settings={...}, scoped_refptr<CefApp> application={...}, void * windows_sandbox_info=0x00000000) Line 214   C++
    libcef.dll!cef_initialize(const _cef_main_args_t * args=0x0a15ff30, const _cef_settings_t * settings=0x0a15fd2c, _cef_app_t * application=0x0f115230, void * windows_sandbox_info=0x00000000) Line 111   C++
>   cefclient.dll!CefInitialize(const CefMainArgs & args={...}, const CefStructBase<CefSettingsTraits> & settings={...}, scoped_refptr<CefApp> application={...}, void * windows_sandbox_info=0x00000000) Line 105   C++


Caused by the following code in chromium-86.0.4240.111/services/service_manager/embedder/main.cc:

Code: Select all
  // A flag to indicate whether Main() has been called before. On Android, we
  // may re-run Main() without restarting the browser process. This flag
  // prevents initializing things more than once.
  static bool is_initialized = false;
#if !defined(OS_ANDROID)
  DCHECK(!is_initialized);
#endif


I found another thread about this error: https://magpcss.org/ceforum/viewtopic.php?f=6&t=16430

Is there any workaround?
It would be quite some work to change the current architecture and use processes instead of a DLL.
robinm2
Techie
 
Posts: 11
Joined: Mon Feb 08, 2021 12:14 pm

Re: Trying to use cefclient as a DLL

Postby robinm2 » Fri Mar 05, 2021 4:00 pm

Hi again,

I tested the solution of spawning a fresh cefclient process for every webpage the main application needs to display. It's too slow for a decent user experience.
So I went back to the DLL design, still based on cefclient. In short:

    - I use DllMain to start RunMain as a thread on DLL_PROCESS_ATTACH.
    - The exported procedure to open a webpage calls message_loop->PostTask(task). "task" creates a RootWindow with the given URL.

It seems to work pretty smoothly as long as I don't close the main application. The instructions after message_loop->Run() in RunMain are never reached, so CEF throws an exception because CefShutdown() has not been called. I've spent the day trying to solve this. Any hint?

Thanks,
robinm2
Techie
 
Posts: 11
Joined: Mon Feb 08, 2021 12:14 pm

Re: Trying to use cefclient as a DLL

Postby robinm2 » Wed Mar 10, 2021 9:41 am

Okay, seems like I've solved the issue for good. Going through a few discussions on the Internet it became clear that you cannot rely on DllMain to do a proper CEF shutdown. When PROCESS_DETACH is reached, all threads have already been killed.

So I changed the architecture again: now I've got a cefclient executable, and a small DLL that provides a layer between the main app and cefclient. The DLL spawns cefclient.exe on PROCESS_ATTACH, and sends a closing message on PROCESS_DETACH. It also passes the main app's requests to cefclient through shared memory. Everything works nicely now.

To wrap up, using cefclient as a DLL is possible if your application provides an easy way to perform logic before shutting down, so that CEF terminates gracefully.
For me it was better not to change anything to the application (large piece of legacy code).
robinm2
Techie
 
Posts: 11
Joined: Mon Feb 08, 2021 12:14 pm

Previous

Return to Support Forum

Who is online

Users browsing this forum: No registered users and 53 guests