Avoid starting multiple windows (processes)

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.

Avoid starting multiple windows (processes)

Postby me12 » Thu Jul 24, 2014 12:02 pm

Hey guys,

I am trying to implement CEF3 in my game engine. Actually I already got a simple test case working. The only annoying thing is that it always opens tons of windows. I figured that this must be because of the multi-process-architecture of CEF3.

I believe these are my options but I am not sure which is the best and if there may be another one:


1. Set single_process = true

I read that this is a bad idea. Besides it crashes with this error message:

Code: Select all
[0724/185204:ERROR:proxy_service_factory.cc(105)] Cannot use V8 Proxy resolver in single process mode.
#
# Fatal error in c:\cef\workspace\cef3-windows-trunk\download\chromium\src\v8\src\v8.cc, line 121
# CHECK(!platform_) failed
#
First-chance exception at 0x00000000 in VektoriaApp.exe: 0xC0000005: Access violation executing location 0x00000000.


Callstack:

Code: Select all
>   00000000()   Unknown
    [Frames below may be incorrect and/or missing]   
    libcef.dll!v8::internal::OS::Abort() Line 815   C++
    libcef.dll!v8::internal::V8::InitializePlatform(v8::Platform * platform) Line 121   C++
    libcef.dll!blink::initialize(blink::Platform * platform) Line 107   C++
    libcef.dll!content::RenderThreadImpl::EnsureWebKitInitialized() Line 792   C++
    libcef.dll!content::RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params & params) Line 1295   C++
    libcef.dll!DispatchToMethod<content::RenderThreadImpl,void (__thiscall content::RenderThreadImpl::*)(ViewMsg_New_Params const &),ViewMsg_New_Params>(content::RenderThreadImpl * obj, void (const ViewMsg_New_Params &) * method, const Tuple1<ViewMsg_New_Params> & arg) Line 548   C++
    libcef.dll!ViewMsg_New::Dispatch<content::RenderThreadImpl,content::RenderThreadImpl,void,void (__thiscall content::RenderThreadImpl::*)(ViewMsg_New_Params const &)>(const IPC::Message * msg, content::RenderThreadImpl * obj, content::RenderThreadImpl * sender, void * parameter, void (const ViewMsg_New_Params &) * func) Line 562   C++
    libcef.dll!content::RenderThreadImpl::OnControlMessageReceived(const IPC::Message & msg) Line 1276   C++
    libcef.dll!content::ChildThread::OnMessageReceived(const IPC::Message & msg) Line 465   C++
    libcef.dll!IPC::ChannelProxy::Context::OnDispatchMessage(const IPC::Message & message) Line 273   C++
    libcef.dll!base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)>::Run(IPC::ChannelProxy::Context * object, const IPC::Message & a1) Line 190   C++
    libcef.dll!base::internal::InvokeHelper<0,void,base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)>,void __cdecl(IPC::ChannelProxy::Context * const &,IPC::Message const &)>::MakeItSo(base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)> runnable, IPC::ChannelProxy::Context * const & a1, const IPC::Message & a2) Line 899   C++
    libcef.dll!base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall IPC::ChannelProxy::Context::*)(IPC::Message const &)>,void __cdecl(IPC::ChannelProxy::Context *,IPC::Message const &),void __cdecl(IPC::ChannelProxy::Context *,IPC::Message)>,void __cdecl(IPC::ChannelProxy::Context *,IPC::Message const &)>::Run(base::internal::BindStateBase * base) Line 1253   C++
    libcef.dll!base::Callback<void __cdecl(void)>::Run() Line 401   C++
    libcef.dll!base::MessageLoop::RunTask(const base::PendingTask & pending_task) Line 460   C++
    libcef.dll!base::MessageLoop::DeferOrRunPendingTask(const base::PendingTask & pending_task) Line 473   C++
    libcef.dll!base::MessageLoop::DoWork() Line 584   C++
    libcef.dll!base::MessagePumpForUI::DoRunLoop() Line 218   C++
    libcef.dll!base::MessagePumpWin::RunWithDispatcher(base::MessagePump::Delegate * delegate, base::MessagePumpDispatcher * dispatcher) Line 65   C++
    libcef.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate) Line 47   C++
    libcef.dll!base::MessageLoop::RunHandler() Line 408   C++
    libcef.dll!base::RunLoop::Run() Line 50   C++
    libcef.dll!base::MessageLoop::Run() Line 302   C++
    libcef.dll!base::Thread::Run(base::MessageLoop * message_loop) Line 175   C++
    libcef.dll!base::Thread::ThreadMain() Line 228   C++
    libcef.dll!base::`anonymous namespace'::ThreadFunc(void * params) Line 78   C++
    [External Code]   


2. Use CEF1

This solution feels bad. I don't know when the support for CEF1 will stop and I believe I am already missing some functionality when using CEF1 instead of CEF3?

3. Have a separate executable using invisible windows?

Is this possible? I mean I would't care if CEF starts multiple processes as long as it does not annoy the user with tons of windows and if it also shuts down all sub processes properly.

4. Any other ideas?
me12
Techie
 
Posts: 31
Joined: Thu Jul 10, 2014 12:46 pm

Re: Avoid starting multiple windows (processes)

Postby TomDigitale » Fri Jul 25, 2014 4:44 am

You're right: it is because of the multi processes architecture.
Actually, when you start any new process (create a CefBrowser will start a new process), the entry point function of this process will be the main function if not precised otherwise. But to prevent your newly created process to execute code purposely for your main process, you should call CefExecuteProcess as a first instruction (or nearly first) : it will "intercept" and execute processes until they finish.
Here's an example with a SFML window created:

Code: Select all
int main(int argc, char** argv)
{
    CefRefPtr<sfw::SFApp> app(new sfw::SFApp);
    CefSettings settings;
    settings.windowless_rendering_enabled = true;

    CefMainArgs main_args;

    int exitCode = CefExecuteProcess(main_args, app.get(), NULL); // This code will intercept "not-main" processes
    if (exitCode >= 0)
    {
         std::exit(0);
    }

    CefInitialize(main_args, settings, app.get(), NULL);


    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Window");
    while (window.isOpen())
    {
         ...
    }
}


Precisely, what I think you are doing (but without any code I'm just guessing) is that you call this function after creating your window, thus creating multiple windows: each processes recreate your window before being "intercepted".

Alternatively, you can precise a separated sub-process executable for your processes to execute (instead of the main function). To read more about it: https://code.google.com/p/chromiumembedded/wiki/GeneralUsage#Separate_Sub-Process_Executable
TomDigitale
Techie
 
Posts: 18
Joined: Fri Mar 14, 2014 6:00 am

Re: Avoid starting multiple windows (processes)

Postby me12 » Fri Jul 25, 2014 12:15 pm

Hey Tom,

thank you very much! That fixed the issue with different windows.

There are still tons of things to do but at least it works: http://youtu.be/bcR-2samj-A :)
me12
Techie
 
Posts: 31
Joined: Thu Jul 10, 2014 12:46 pm


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 37 guests