Object reference incorrectly held at CefShutdown

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: Object reference incorrectly held at CefShutdown

Postby pascalkhoury » Wed Jun 08, 2022 8:52 am

Indeed I do get separate OnBeforeClose for the main window and the popup window.
But that doesn't solve the problem that sometimes CefShutdown could be called while the Browser or the LifeSpanHandler are IN THE PROCESS of being destructed.

1. I request that all the browsers close from the main application thread using browser->GetHost()->CloseBrowser( true ).
2. I wait for an event to be set to know that all browsers have called OnBeforeClose.
3. I get OnBeforeClose callbacks in another thread (CEF UI thread).
4. Once all browsers have called OnBeforeClose, I set an event (from the CEF UI thread) to signal that I can call CefShutdown.

Sometimes CefShutdown is called while OnBeforeClose didn't completely return, or some Cef object is currently in its destructor, like the CefClient.
This is because I set the event in OnBeforeClose.

My question is: is there not a callback that I can use that is called when everything is completely closed? If not then I don't see how I can cleanly shutdown without intermittent failures due to different timing in execution.
pascalkhoury
Techie
 
Posts: 25
Joined: Fri Apr 15, 2022 8:21 am

Re: Object reference incorrectly held at CefShutdown

Postby magreenblatt » Wed Jun 08, 2022 9:32 am

CBrowserHandler::OnAfterCreated browser 1
Application is shutting down. Close all open browsers
CBrowserHandler::DoClose browser 1
CBrowserHandler::OnBeforeClose browser 1
CBrowserManager::OnBeforeClose: All browsers closed
Calling CefShutdown

Does this output indicate that OnBeforeClose was called for the main browser and the popup browser?

If I’m misunderstanding your previous posts then please start over and explain the problem more clearly.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: Object reference incorrectly held at CefShutdown

Postby pascalkhoury » Wed Jun 08, 2022 10:15 am

magreenblatt wrote:
CBrowserHandler::OnAfterCreated browser 1
Application is shutting down. Close all open browsers
CBrowserHandler::DoClose browser 1
CBrowserHandler::OnBeforeClose browser 1
CBrowserManager::OnBeforeClose: All browsers closed
Calling CefShutdown

Does this output indicate that OnBeforeClose was called for the main browser and the popup browser?

This output is in the case of only 1 main browser.

I will explain more clearly because I probably confused you with mentioning the popup browsers.

In my app, I have a class that keeps track of all opened browsers; called CBrowserManager.

When I want to exit the app, I first call CBrowserManager::CloseAllBorwsers from the main application thread. CloseAllBorwsers will loop over all existing browsers and call browser->GetHost()->CloseBrowser( true ).

I then wait for a windows Event object to be set that signals that all the browsers have called OnBeforeClose(). To wait for that event, I use the MsgWaitForMultipleObjectsEx function (in combination with TranslateMessage and DispatchMessage).

The windows event object is set (using SetEvent) when OnBeforeClose has been called for the last browser.

When that event is set, CBrowserManager::CloseAllBorwsers returns and then CefShutdown is called.

Simplified code:
Code: Select all
void CCefApp::OnPreShutdown()
{
  CBrowserManager::Instance().CloseAllBrowsers(); // this will wait for all the browsers' OnBeforeClose to be called
  CefShutdown();
}

void CBrowserManager::CloseAllBrowsers()
{
  _browsersClosedEvent.reset();
  for ( auto const &browser : _browsers )
      browser->GetHost()->CloseBrowser( true );

  // wait for the event to be triggered before returning
  _browsersClosedEvent.wait();
}

void CBrowserManager::OnBeforeClose( CefRefPtr< CefBrowser > browser )
{
  _browsers.erase( browser->GetIdentifier() );

  if ( _browsers.empty() == true )
  {
    _browsersClosedEvent.trigger();
    //::Sleep( 100 ); // adding this sleep will guarantee that the AssertNotShutdown is triggered
  }
}


The problem I have is that sometimes I still get the AssertNotShutdown assert. This is because when I set the event to signal that all browsers have closed, CefShutdown might be called even BEFORE the last OnBeforeClose had the time to return. If that happens, then some Cef objects will go out of scope AFTER I have called CefShutdown --> AssertNotShutdown is triggered.
See this callstack:
Code: Select all
libcef.dll!logging::LogMessage::~LogMessage() Line 909   C++
libcef.dll!logging::LogMessage::~LogMessage() Line 593   C++
libcef.dll!logging::CheckError::~CheckError() Line 109   C++
libcef.dll!shutdown_checker::AssertNotShutdown() Line 32   C++
[Inline Frame] libcef.dll!CefBrowserCppToC::~CefBrowserCppToC() Line 423   C++
libcef.dll!CefBrowserCppToC::~CefBrowserCppToC() Line 422   C++
libcef.dll!CefCppToCRefCounted<CefBrowserCppToC,CefBrowser,_cef_browser_t>::Release() Line 86   C++
libcef.dll!CefCppToCRefCounted<CefBrowserCppToC,CefBrowser,_cef_browser_t>::struct_release(_cef_base_ref_counted_t * base) Line 167   C++
LmsHq_DataModelVC_D2DFDispCef_v1.dll!CefCToCppRefCounted<CefBrowserCToCpp,CefBrowser,_cef_browser_t>::UnderlyingRelease() Line 78   C++
LmsHq_DataModelVC_D2DFDispCef_v1.dll!CefCToCppRefCounted<CefBrowserCToCpp,CefBrowser,_cef_browser_t>::Release() Line 154   C++
LmsHq_DataModelVC_D2DFDispCef_v1.dll!scoped_refptr<CefBrowser>::Release(CefBrowser * ptr) Line 356   C++
LmsHq_DataModelVC_D2DFDispCef_v1.dll!scoped_refptr<CefBrowser>::~scoped_refptr<CefBrowser>() Line 258   C++

************************ I call CefShutdown somewhere here from another thread ************************

LmsHq_DataModelVC_D2DFDispCef_v1.dll!LmsHq::DataModelVC::D2DFDispCef::CBrowserManager::OnBeforeClose(scoped_refptr<CefBrowser> ac_xBrowser) Line 36   C++
LmsHq_DataModelVC_D2DFDispCef_v1.dll!`anonymous namespace'::life_span_handler_on_before_close(_cef_life_span_handler_t * self, _cef_browser_t * browser) Line 207   C++
libcef.dll!CefLifeSpanHandlerCToCpp::OnBeforeClose(scoped_refptr<CefBrowser> browser) Line 162   C++


What happens to produce the above callstack:
- I have 1 open browser
- I request to close it from the main thread
- OnBeforeClose is called on thread A
- The event to signal that all browsers are closed is set from thread A
- I added a ::Sleep after I set the event
- Thread A goes to sleep
- CefShutdown is called from the main thread
- Thread A wakes up and OnBeforeClose returns
- When OnBeforeClose returns, the browser argument goes out of scope and its destructor is called
- The assert is triggered in the destructor of CefBrowserCppToC because CefShutdown has already been called

I added the Sleep because it's the simplest way to reproduce the problem. But I had AssertNotShutdown trigger without the Sleep many times before.

And my question is: Am I doing something fundamentally wrong (using the callbacks in the wrong way or something) to know when I can call CefShutdown?
If yes then what is the proper way to do it?

I hope this is more clear now.

Thanks
pascalkhoury
Techie
 
Posts: 25
Joined: Fri Apr 15, 2022 8:21 am

Re: Object reference incorrectly held at CefShutdown

Postby magreenblatt » Wed Jun 08, 2022 12:28 pm

The problem I have is that sometimes I still get the AssertNotShutdown assert. This is because when I set the event to signal that all browsers have closed, CefShutdown might be called even BEFORE the last OnBeforeClose had the time to return.

Agreed, this is likely the problem.

And my question is: Am I doing something fundamentally wrong (using the callbacks in the wrong way or something) to know when I can call CefShutdown?
If yes then what is the proper way to do it?

You can use CefPostTask to signal the event from the UI thread after the OnBeforeClose call stack has unwound.
magreenblatt
Site Admin
 
Posts: 12382
Joined: Fri May 29, 2009 6:57 pm

Re: Object reference incorrectly held at CefShutdown

Postby pascalkhoury » Thu Jun 09, 2022 7:05 am

Using CefPostTask to signal the event from the UI thread works!

Thanks
pascalkhoury
Techie
 
Posts: 25
Joined: Fri Apr 15, 2022 8:21 am

Previous

Return to Support Forum

Who is online

Users browsing this forum: No registered users and 44 guests