Correct way to close CEF window in multi-threaded mode

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.

Correct way to close CEF window in multi-threaded mode

Postby skocef » Fri Sep 08, 2017 5:00 am

With multi_threaded_message_loop = true, what is proper way to destroy browser window?

My Windows MDI app opens several browsers and everything works fine until I open and close browsers quickly, then the app crashes somewhere deep in libcef.dll. Looks as I'm not closing the window properly and CEF is trying to access some deleted object. I do it in the way copied from some example:

auto hBrowser = m_cefBrowser->GetHost()->GetWindowHandle();
::DestroyWindow(hBrowser);

Is there anything I should do differently in multi_threaded_message_loop mode?

The stack:
> libcef.dll!`anonymous namespace'::PureCall() Line 21 C++
libcef.dll!_purecall() Line 29 C++
libcef.dll!content::RenderFrameHostImpl::OnUpdateTitle(const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > & title={...}, blink::WebTextDirection title_direction=WebTextDirectionLeftToRight) Line 1684 + 0x24 bytes C++
libcef.dll!IPC::MessageT<FrameHostMsg_UpdateTitle_Meta,std::tuple<std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >,enum blink::WebTextDirection>,void>::Dispatch<content::RenderFrameHostImpl,content::RenderFrameHostImpl,void,void (__thiscall content::RenderFrameHostImpl::*)(std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > const &,enum blink::WebTextDirection)>(const IPC::Message * msg=0x071e4738, content::RenderFrameHostImpl * obj=0x073baad0, content::RenderFrameHostImpl * sender=0x073baad0, void * parameter=0x00000000, void (const std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > &, blink::WebTextDirection)* func=0x1180f06c) Line 121 + 0x10 bytes C++
libcef.dll!content::RenderFrameHostImpl::OnMessageReceived(const IPC::Message & msg={...}) Line 592 + 0x38 bytes C++
libcef.dll!content::RenderProcessHostImpl::OnMessageReceived(const IPC::Message & msg={...}) Line 1774 + 0x5 bytes C++
libcef.dll!IPC::ChannelProxy::Context::OnDispatchMessage(const IPC::Message & message={...}) Line 285 C++
libcef.dll!base::internal::Invoker<base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall content::InputEventFilter::*)(IPC::Message const &)>,content::InputEventFilter * const,IPC::Message const &>,void __cdecl(void)>::Run(base::internal::BindStateBase * base=0x071e4728) Line 346 C++
libcef.dll!base::debug::TaskAnnotator::RunTask(const char * queue_function=0x12effd1c, const base::PendingTask & pending_task={...}) Line 51 + 0x5 bytes C++
libcef.dll!base::MessageLoop::RunTask(const base::PendingTask & pending_task={...}) Line 491 C++
libcef.dll!base::MessageLoop::DoWork() Line 622 C++
libcef.dll!base::MessagePumpForUI::DoRunLoop() Line 263 C++
libcef.dll!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate=0x06f47db8) Line 142 C++
libcef.dll!base::RunLoop::Run() Line 36 C++
libcef.dll!base::Thread::Run(base::MessageLoop * message_loop=0x06f47db8) Line 205 + 0xf bytes C++
libcef.dll!base::Thread::ThreadMain() Line 259 C++
libcef.dll!base::`anonymous namespace'::ThreadFunc(void * params=0x06f24168) Line 85 C++
skocef
Newbie
 
Posts: 6
Joined: Fri Sep 08, 2017 4:36 am

Re: Correct way to close CEF window in multi-threaded mode

Postby magreenblatt » Fri Sep 08, 2017 10:35 am

Where are you calling DestroyWindow from? See comments on CefLifeSpanHandler::DoClose for proper shutdown handling.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: Correct way to close CEF window in multi-threaded mode

Postby skocef » Mon Sep 11, 2017 3:12 am

I'm calling it when user closes browser's parent window (MDI child).

From all I read about the subject, there are two ways to close the browser: using CloseBrowser and simple destroying browser's parent window:

The CEF window will be destroyed automatically if the parent window is destroyed. If the CEF window is the top-level frame window, or if you want to close the CEF window explicitly, then you can call either CloseBrowser or use OS functions like DestroyWindow. You don't need to do both
.

I have tried both ways in all possible combinations and the result is always the same: the browser closes and its external process exists normally if I wait page loading completes. But if the page is still loading, the app crashes after several open/close iterations (3-5). Crash location can differ but idea is always the same: invalid callback pointer.

Is there any example that opens/closes several browser windows? All examples I found are SDI, i.e. browser window created only once and closed together with app's main window.
skocef
Newbie
 
Posts: 6
Joined: Fri Sep 08, 2017 4:36 am

Re: Correct way to close CEF window in multi-threaded mode

Postby skocef » Mon Sep 11, 2017 4:45 am

CEFMFC sample (https://bitbucket.org/TSS_DEV/cef-mfc) has this problem too. Set it to multi-threaded mode (by setting multi_threaded_message_loop on and removing call to CefDoMessageLoopWork) and now it is only question of amount of NewBrowser/Close repetitions until it crashes in same manner as my app. With multi_threaded_message_loop OFF, the sample works properly.

Any ideas what I could check/do more?
skocef
Newbie
 
Posts: 6
Joined: Fri Sep 08, 2017 4:36 am

Re: Correct way to close CEF window in multi-threaded mode

Postby magreenblatt » Mon Sep 11, 2017 11:41 am

Does the crash reproduce in cefclient when running with `--multi-threaded-message-loop`? If not, I suggest you review how you're storing CEF object references in your code and make sure you're always using CefRefPtr<>.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 80 guests