Releasing CefV8Handler without refreshing page

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.

Releasing CefV8Handler without refreshing page

Postby hunterlaux » Mon Sep 17, 2018 4:15 pm

I'm wondering when CefV8Handlers are supposed to be deleted.

Consider this code.
Code: Select all
#include "examples/shared/app_factory.h"

namespace shared {

   CefRefPtr<CefBrowser> g_browser;

   void ExecuteJavascript(const std::string &str)
   {
      if (g_browser)
      {
         CefRefPtr<CefFrame> frame = g_browser->GetMainFrame();
         frame->ExecuteJavaScript(str, frame->GetURL(), 0);
      }
   }

   class My8Handler : public CefV8Handler {
   public:
      My8Handler() {
         ExecuteJavascript("console.log('constructed callback handler')");
      }

      ~My8Handler() {
         ExecuteJavascript("console.log('destroyed callback handler')");
      }

      virtual bool Execute(const CefString& name,
         CefRefPtr<CefV8Value> object,
         const CefV8ValueList& arguments,
         CefRefPtr<CefV8Value>& retval,
         CefString& exception) OVERRIDE {

         // Function does not exist.
         return false;
      }

      IMPLEMENT_REFCOUNTING(My8Handler);
   };


   class WindowHandler : public CefV8Handler {
   public:
      WindowHandler() {}

      virtual bool Execute(const CefString& name,
         CefRefPtr<CefV8Value> object,
         const CefV8ValueList& arguments,
         CefRefPtr<CefV8Value>& retval,
         CefString& exception) OVERRIDE {
         if (name == "createHandle") {
            CefRefPtr<CefV8Handler> handler = new My8Handler();

            CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("somefunction", handler);
            retval = func;

            return true;
         }

         return false;
      }

      IMPLEMENT_REFCOUNTING(WindowHandler);
   };

   class RendererApp :
      public CefApp,
      public CefRenderProcessHandler {
   public:
      RendererApp() {
      }

      CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE {
         return this;
      }

      void OnContextCreated(CefRefPtr<CefBrowser> browser,
         CefRefPtr<CefFrame> frame,
         CefRefPtr<CefV8Context> context) OVERRIDE {
         g_browser = browser;
         CefRefPtr<CefV8Value> object = context->GetGlobal();

         CefRefPtr<CefV8Handler> handler = new WindowHandler();

         CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("createHandle", handler);

         object->SetValue("createHandle", func, V8_PROPERTY_ATTRIBUTE_NONE);
      }

      void OnContextReleased(CefRefPtr<CefBrowser> browser,
         CefRefPtr<CefFrame> frame,
         CefRefPtr<CefV8Context> context) OVERRIDE {
         g_browser = nullptr;
      }
   private:
      IMPLEMENT_REFCOUNTING(RendererApp);
      DISALLOW_COPY_AND_ASSIGN(RendererApp);
   };

CefRefPtr<CefApp> CreateRendererProcessApp() {
  return new RendererApp();
}

}  // namespace shared


And let's say I create 2000 My8Handler handlers.

I ran this in the remote debugger.
Code: Select all
var i;
for (i = 0; i < 2000; i++) {
  window.createHandle();
}
2000(index):1 constructed callback handler
ƒ somefunction() { [native code] }


I would expect that some(if not all) of these handlers would be deleted when "somefunction" is garbage collected.

I'm using Cef 3.3497.1827.ga4f7e36_windows32.

If I reload the page CefV8Handlers are indeed deleted, although if I allocate 2000 I get a stack overflow while they are deleting themselves. 200 or so seems to work just fine.

Am I missing something?
hunterlaux
Techie
 
Posts: 22
Joined: Fri Nov 17, 2017 5:50 pm

Re: Releasing CefV8Handler without refreshing page

Postby Czarek » Wed Sep 19, 2018 6:55 am

Can't you create just one handler and share it? Also there seems to be a logic error in your code, you're creating a function, but in Execute you return false, however you don't set any exception.
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am

Re: Releasing CefV8Handler without refreshing page

Postby hunterlaux » Wed Sep 19, 2018 11:50 am

Yes in the example I can share the handler, but I'm trying to solve a bigger problem here. I intend to use the handler for a proxy to a native object.

You're right about that returning false thing, but in my testing, I'm not actually executing that code. I'm just trying to illustrate the leak.

It seems that this might be the culprit in cef_v8value_create_function
Code: Select all
  CefRefPtr<CefV8Value> _retval = CefV8Value::CreateFunction(
      CefString(name), CefV8HandlerCToCpp::Wrap(handler));


The ref count to the handler isn't decremented when it exits the C thunk.
hunterlaux
Techie
 
Posts: 22
Joined: Fri Nov 17, 2017 5:50 pm

Re: Releasing CefV8Handler without refreshing page

Postby Czarek » Wed Sep 19, 2018 1:05 pm

What if you release them manually by calling handler->Release() in OnContextReleased? (and stop keeping any references to it as well)
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am

Re: Releasing CefV8Handler without refreshing page

Postby hunterlaux » Wed Sep 19, 2018 5:31 pm

Now that I have a better understanding of how those wrapper structs work it's clear now that I was barking up the wrong tree. That wrapper thing is neat.

I'm attempting to figure out why the V8TrackerObject associated with that function only gets destroyed when I reload the entire page.
hunterlaux
Techie
 
Posts: 22
Joined: Fri Nov 17, 2017 5:50 pm

Re: Releasing CefV8Handler without refreshing page

Postby Czarek » Thu Oct 04, 2018 12:30 pm

Also you could try to reproduce the issue in cefclient or in unit tests. If it reproduces it is likely to be fixed.
Maintainer of the CEF Python, PHP Desktop and CEF C API projects. My LinkedIn.
User avatar
Czarek
Virtuoso
 
Posts: 1927
Joined: Sun Nov 06, 2011 2:12 am


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 53 guests