OnBrowserDestroyed never called

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.

OnBrowserDestroyed never called

Postby digory » Mon Nov 21, 2016 5:14 am

I'm trying to use OnBrowserCreated and OnBrowserDestroyed callbacks in the renderer process.
OnBrowserCreated is reliably called, but OnBrowserDestroyed is not.
In my particular case, the browser is a child window inside a parent window that lives
longer than the browser, so I need to manually call CloseBrowser.

Here's part of my implementation of the CefApp subclass:

Code: Select all
class KisCefApp:
   public CefApp,
   public CefBrowserProcessHandler,
   public CefRenderProcessHandler
{
   public:
      virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override { return this; }
      virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }
      virtual void OnBrowserCreated (CefRefPtr<CefBrowser> browser) override;
      virtual void OnBrowserDestroyed (CefRefPtr<CefBrowser> browser) override;
      virtual void OnContextCreated (CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
         CefRefPtr<CefV8Context> context) override;
      virtual void OnContextReleased (CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
         CefRefPtr<CefV8Context> context) override;
}


Here's part of my debug log:

Code: Select all
[1121/105530:INFO:kiscefclient.cpp(36)] KisCefClient::createBrowser
[1121/105531:INFO:kiscefclient.cpp(102)] KisCefClient::OnAfterCreated
[1121/105645:INFO:kiscefclient.cpp(145)] KisCefClient::OnLoadingStateChange: isLoading=true
[1121/105646:INFO:kiscefapp.cpp(102)] KisCefApp::OnBrowserCreated: 1
[1121/105646:ERROR:singleton_hwnd.cc(34)] Cannot create windows on non-UI thread!
[1121/105648:INFO:kiscefclient.cpp(184)] KisCefClient::OnAddressChange
[1121/105648:INFO:kiscefapp.cpp(123)] KisCefApp::OnContextCreated
[1121/105648:INFO:kiscefclient.cpp(145)] KisCefClient::OnLoadingStateChange: isLoading=false

[1121/105700:INFO:kiscefclient.cpp(65)] KisCefClient::destroyBrowser: about to call CloseBrowser
[1121/105700:INFO:kiscefclient.cpp(118)] KisCefClient::DoClose: Closing the browser
[1121/105700:INFO:kiscefclient.cpp(138)] KisCefClient::OnBeforeClose


As the log shows, OnAfterCreated fires first, then OnBrowserCreated is called. When my application
decides the browser should be closed, it calls CloseBrowser. DoClose is called first, then OnBeforeClose.
OnBrowserDestroyed is not called.

Here's my implementation of DoClose:

Code: Select all
   if (browser->IsSame (m_browser))
      {
      LOG (INFO) << "KisCefClient::DoClose: Closing the browser";
      HWND hwnd = getHwnd();
      ::DestroyWindow (hwnd);
      return true;  // true=we've handled the event ourselves; do not send WM_CLOSE
      }
   else
      {
      LOG (INFO) << "KisCefClient::DoClose: Closing a sub-browser (may be dev tools)";
      return false;  // false=close the window; WM_CLOSE will bubble up to the parent window
      }


The reason why I call DestroyWindow from DoClose is to prevent the WM_CLOSE from bubbling up and closing the parent window. See http://magpcss.org/ceforum/viewtopic.php?f=6&t=14670.

Why is OnBrowserDestroyed never called?
digory
Expert
 
Posts: 118
Joined: Wed Oct 26, 2016 3:13 am

Re: OnBrowserDestroyed never called

Postby magreenblatt » Mon Nov 21, 2016 11:13 am

As mentioned previously OnBrowserDestroyed will not be called if the renderer process is also terminated. If you have only one CefBrowser then that will be the case.
magreenblatt
Site Admin
 
Posts: 12406
Joined: Fri May 29, 2009 6:57 pm

Re: OnBrowserDestroyed never called

Postby digory » Tue Nov 22, 2016 5:02 am

Ah, now I actually get what you meant. I've added a LOG to the destructor of the renderer's CefApp instance. It is not called though.

The constructor of KisCepApp is called three times, once per process:-
Code: Select all
[1122/104801:INFO:kiscefapp.cpp(34)] KisCefApp::KisCefApp constructor
[1122/104803:INFO:kiscefapp.cpp(34)] KisCefApp::KisCefApp constructor
[1122/104811:INFO:kiscefclient.cpp(102)] KisCefClient::OnAfterCreated: actual browser
[1122/104816:INFO:kiscefapp.cpp(34)] KisCefApp::KisCefApp constructor
[1122/104816:INFO:kiscefapp.cpp(114)] KisCefApp::OnBrowserCreated: 1
[1122/104816:ERROR:singleton_hwnd.cc(34)] Cannot create windows on non-UI thread!
[1122/104817:INFO:kiscefclient.cpp(184)] KisCefClient::OnAddressChange
[1122/104817:INFO:kiscefapp.cpp(138)] KisCefApp::OnContextCreated


At this point, there was only a single browser. Here's what happened when I closed it through CloseBrowser:-
Code: Select all
[1122/104832:INFO:kiscefclient.cpp(65)] KisCefClient::destroyBrowser: about to call CloseBrowser
[1122/104832:INFO:kiscefclient.cpp(118)] KisCefClient::DoClose: Closing the browser
[1122/104832:INFO:kiscefclient.cpp(138)] KisCefClient::OnBeforeClose


Note that the renderer's process destructor ~KisCefApp is NOT called, neither is OnBrowserDestroyed. Next, I opened another browser:-
Code: Select all
[1122/104837:INFO:kiscefclient.cpp(36)] KisCefClient::createBrowser
[1122/104838:INFO:kiscefclient.cpp(102)] KisCefClient::OnAfterCreated: actual browser
[1122/104843:INFO:kiscefapp.cpp(34)] KisCefApp::KisCefApp constructor
[1122/104843:INFO:kiscefapp.cpp(114)] KisCefApp::OnBrowserCreated: 2
[1122/104843:ERROR:singleton_hwnd.cc(34)] Cannot create windows on non-UI thread!
[1122/104843:INFO:kiscefclient.cpp(184)] KisCefClient::OnAddressChange
[1122/104843:INFO:kiscefapp.cpp(138)] KisCefApp::OnContextCreated


Interestingly, the above shows that another instance of KisCefApp is created, so the previous renderer process may have terminated without the destructor being called? Anyway, here's what happened when I opened another browser while the previous one was still open:-
Code: Select all
[1122/104846:INFO:kiscefclient.cpp(36)] KisCefClient::createBrowser
[1122/104846:INFO:kiscefclient.cpp(102)] KisCefClient::OnAfterCreated: actual browser
[1122/104850:INFO:kiscefapp.cpp(34)] KisCefApp::KisCefApp constructor
[1122/104850:INFO:kiscefapp.cpp(114)] KisCefApp::OnBrowserCreated: 3
[1122/104850:ERROR:singleton_hwnd.cc(34)] Cannot create windows on non-UI thread!
[1122/104850:INFO:kiscefclient.cpp(184)] KisCefClient::OnAddressChange
[1122/104850:INFO:kiscefapp.cpp(138)] KisCefApp::OnContextCreated


Then I closed one of the browsers:-
Code: Select all
[1122/104856:INFO:kiscefclient.cpp(65)] KisCefClient::destroyBrowser: about to call CloseBrowser
[1122/104857:INFO:kiscefclient.cpp(118)] KisCefClient::DoClose: Closing the browser
[1122/104857:INFO:kiscefclient.cpp(138)] KisCefClient::OnBeforeClose


Note that OnBrowserDestroyed is NOT called even though there was still one browser open at this point. When I closed that one, too:-
Code: Select all
[1122/104901:INFO:kiscefclient.cpp(65)] KisCefClient::destroyBrowser: about to call CloseBrowser
[1122/104901:INFO:kiscefclient.cpp(118)] KisCefClient::DoClose: Closing the browser
[1122/104901:INFO:kiscefclient.cpp(138)] KisCefClient::OnBeforeClose


When I finally closed the application, the destructor was called once, probably for the browser process:-
Code: Select all
[1122/104909:FATAL:browser_main.cc(234)] Check failed: 0 == CefBrowserContext::DebugObjCt (0 vs. 1)
[1122/104916:INFO:kiscefapp.cpp(72)] KisCefApp: CefExecuteProcess returned with: 0
[1122/104916:INFO:kiscefapp.cpp(42)] KisCefApp::~KisCefApp destructor


To conclude, my questions are:
[*] Why is the destructor of CefApp not called when a renderer process is terminated?
[*] Is there any hook to notify the renderer process before it is terminated (other than the destructor)?
[*] Why is OnBrowserDestroyed not called even when there is still one browser alive?
digory
Expert
 
Posts: 118
Joined: Wed Oct 26, 2016 3:13 am

Re: OnBrowserDestroyed never called

Postby magreenblatt » Tue Nov 22, 2016 12:04 pm

Are the browsers pointing to the same origin (protocol + host)?

When the renderer process is terminated no cleanup code is executed. It's equivalent to calling the _exit() function.
magreenblatt
Site Admin
 
Posts: 12406
Joined: Fri May 29, 2009 6:57 pm

Re: OnBrowserDestroyed never called

Postby digory » Wed Nov 23, 2016 3:17 am

OK, that explains why the destructor is never called. I guess that's fine, because all I'm trying to do is free up some memory.

Yes, I opened the same URL in the new browsers. I've just tried it again, this time opening a different URL each time. Still, OnBrowserDestroyed is never called (or at least it does not show up in the log).
digory
Expert
 
Posts: 118
Joined: Wed Oct 26, 2016 3:13 am

Re: OnBrowserDestroyed never called

Postby magreenblatt » Wed Nov 23, 2016 9:20 am

Can you use Process Explorer to verify that it's not creating a separate renderer process for each browser instance?
magreenblatt
Site Admin
 
Posts: 12406
Joined: Fri May 29, 2009 6:57 pm

Re: OnBrowserDestroyed never called

Postby digory » Mon Nov 28, 2016 3:26 am

I downloaded the tool and checked it. It does create a renderer process per browser instance. There is also a process with type gpu. When closing a browser, the corresponding renderer process terminates. The log still does not show any sign of OnBrowserDestroyed.
digory
Expert
 
Posts: 118
Joined: Wed Oct 26, 2016 3:13 am

Re: OnBrowserDestroyed never called

Postby digory » Mon Nov 28, 2016 7:19 am

I noticed the following log entries I haven't seen before:

Code: Select all
[1128/130728:ERROR:dxva_video_decode_accelerator_win.cc(345)] The eglQueryDeviceAttribEXT function failed to get the device
[1128/130728:ERROR:mf_helpers.cc(12)] Error in dxva_video_decode_accelerator_win.cc on line 345


They appear right after Cef has been initialized, but before a browser instance is created. I guess it's related to WebGL and was caused because I replaced my developer machine with a new one.

Additionally, the following log entries would appear when closing a browser instance while another instance is still open:

Code: Select all
[1128/130746:ERROR:singleton_hwnd.cc(34)] Cannot create windows on non-UI thread!
[1128/130756:ERROR:singleton_hwnd.cc(34)] Cannot create windows on non-UI thread!


When closing the second browser instance, the log file is touched, but no additional log entry is written. According to http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11415, these log entries are nothing to worry about though. Right?

Finally, when closing the application, the following assertion fails (even in Release mode):

Code: Select all
[1128/130907:FATAL:browser_main.cc(234)] Check failed: 0 == CefBrowserContext::DebugObjCt (0 vs. 1)


This is a known issue https://bitbucket.org/chromiumembedded/cef/issues/1680/windows-2454-crash-on-shutdown-with-multi, but still not assigned to anybody.

Is it possible that one of these log entries show why OnBrowserDestroyed is never called?
digory
Expert
 
Posts: 118
Joined: Wed Oct 26, 2016 3:13 am

Re: OnBrowserDestroyed never called

Postby magreenblatt » Mon Nov 28, 2016 12:06 pm

digory wrote:I downloaded the tool and checked it. It does create a renderer process per browser instance. There is also a process with type gpu. When closing a browser, the corresponding renderer process terminates. The log still does not show any sign of OnBrowserDestroyed.

Not getting an OnBrowserDestroyed callback is expected when there is only one browser per renderer process.

Why do you need the OnBrowserDestroyed callback?
magreenblatt
Site Admin
 
Posts: 12406
Joined: Fri May 29, 2009 6:57 pm

Re: OnBrowserDestroyed never called

Postby digory » Tue Nov 29, 2016 5:00 am

I allocate some memory in OnBrowserCreated. So the natural place to free it is in OnBrowserDestroyed. It is not absolutely necessary that OnBrowserDestroyed be called if the process is terminated, because in that case the OS will free the memory. However, from the point of view of having a clean API, OnBrowserDestroyed should always be called even if the renderer process is being terminated. For instance, if I was to allocate some system-wide resource that's not automatically freed, say a pipe or global memory, then I would have a hard time finding a good place where to free it.
digory
Expert
 
Posts: 118
Joined: Wed Oct 26, 2016 3:13 am

Next

Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 42 guests