CppCall upon registered javascript function results in crash

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.

CppCall upon registered javascript function results in crash

Postby OneLiner » Mon Jan 28, 2019 3:41 pm

I am a CEF-newbie and I am planning to integrate CEF (cef_binary_3.3578.1863.gbf8cff2_windows32) into my application.
I am actually developping on windows 7 using visual Studio 2017.

As a preparation i actually am trying to implement the following sequence:

When a User pushes a Button in the toolbar, from the handler Method, a message gets sent to the RenderProcessHandler (ClientApp).
As a result a javascript-function, that has been registered afore, should be called.

1.) The Registration of the javascript already is working:

//========================================
// A.) this function definitly gets called during program start.
//========================================
Code: Select all
 1  void ClientApp::OnContextCreated(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context) {
     2
     3    CefRefPtr<CefV8Handler> handler = new MyV8Handler(this);
     4
     5
     6    // Retrieve the context's window object.
     7    CefRefPtr<CefV8Value> object = context->GetGlobal();
     8    object->SetValue("register",CefV8Value::CreateFunction("register", handler),V8_PROPERTY_ATTRIBUTE_NONE);
     9  }



//========================================
// B.) And MyHandler actually looks like this.
//========================================

Code: Select all
  1  CefV8Value   *MyV8Handler::callback_func_=NULL; // static variable
     2  CefRefPtr<CefV8Context> MyV8Handler::callback_context_ = NULL; // static variable
     3
     4  MyV8Handler::MyV8Handler(ClientApp *) {
     5  }
     6
     7  bool MyV8Handler::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval,

CefString& exception) {
     8
     9    if (name == "register") {
    10      if (arguments.size() == 1 && arguments[0]->IsFunction()) {
    11        callback_func_ = arguments[0];
    12        callback_context_ = CefV8Context::GetCurrentContext();
    13        CefV8ValueList args;
    14        MyV8Handler::callback_func_->ExecuteFunctionWithContext(callback_context_, NULL, args);
    15        return true;
    16      }
    17    }
    18
    19    // Function does not exist.
    20    return false;
    21  }



//========================================
// C.) The Javascript function that gets registered: (works)
//========================================

Code: Select all
  1  <script>
     2      function myFunc() {
     3         alert("Hello From Javascript!");
     4      };
     5      window.register(myFunc);
     6  </script>


With the exectution of line B.)14 a messagebox appears. ("Hello From Javascript!")
So we know, that the registration has been successfully completed.

//========================================
// D.) Now, if the user pushes the Toolbar button, the following handler gets called: (works)
//========================================
Code: Select all
1  void CCEFMFCApp::OnAppAbout(){
     2    CCEFMFCView *pView = (CCEFMFCView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
     3    CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("TESTA");
     4    pView->m_cefBrowser->SendProcessMessage(PID_RENDERER,msg);
     5  }


//========================================
// E.) As a result this Method gets called (works), but crashes in lcodeline E)14 - within >ExecuteFunctionWithContext(...)
//========================================
Code: Select all
  1  bool ClientApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message){
     2    const std::string& msg = message->GetName();
     3
     4    if (CefCurrentlyOn(TID_RENDERER))
     5    {
     6      if (MyV8Handler::callback_func_ != NULL){
     7
     8        CefRefPtr<CefFrame> frame = browser->GetMainFrame();
     9        CefRefPtr<CefV8Context> v8Context = frame->GetV8Context();
    10        if (v8Context != NULL)
    11        {
    12          CefV8ValueList args;
    13          MyV8Handler::callback_func_->ExecuteFunctionWithContext(v8Context, NULL, args);
    14        }
    15      }
    16      return true;
    17    }
    18    return false;
    19  }


I also already tried to use MyV8Handler::(callback_context_, NULL, args); without success.

What action is required, that the javascript function gets called as reaction upon the user pushing the toolbar button?

Thank you, for having a look...
OneLiner
Techie
 
Posts: 33
Joined: Mon Jan 28, 2019 5:58 am

Re: CppCall upon registered javascript function results in c

Postby magreenblatt » Mon Jan 28, 2019 4:01 pm

You need to call Enter/Exit on v8Context to avoid the crash.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: CppCall upon registered javascript function results in c

Postby magreenblatt » Mon Jan 28, 2019 4:03 pm

magreenblatt wrote:You need to call Enter/Exit on v8Context to avoid the crash.

Actually, that's only necessary for ExecuteFunction(). With ExecuteFunctionWithContext() you should be using MyV8Handler::callback_context_ instead of frame->GetV8Context(). If that doesn't help, please post the symbolized call stack for the crash.
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: CppCall upon registered javascript function results in c

Postby magreenblatt » Mon Jan 28, 2019 4:05 pm

Using static members is also a bad idea if you're planning to load multiple pages or frames in your app. For a better pattern see https://bitbucket.org/chromiumembedded/ ... t-bindings
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: CppCall upon registered javascript function results in c

Postby OneLiner » Tue Jan 29, 2019 8:58 am

Thank you for answering, now i changed the code like this:
Code: Select all
bool ClientApp::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message){
  const std::string& msg = message->GetName();

  if (CefCurrentlyOn(TID_RENDERER))
  {
    if (MyV8Handler::callback_func_ != NULL){       
      if (MyV8Handler::callback_context_ != NULL){
        CefV8ValueList args;
        MyV8Handler::callback_func_->ExecuteFunctionWithContext(MyV8Handler::callback_context_, NULL, args);
      }
    }
    return true;
  }
  return false;
}

but it keeps crashing.

Sourceline_Crash_calling_Javascript_from_cpp_command_handler.PNG
the Sourceline, shown in the debugger ...
Sourceline_Crash_calling_Javascript_from_cpp_command_handler.PNG (62.73 KiB) Viewed 5708 times
Crash_calling_Javascript_from_cpp_command_handler.PNG
Symbolized Call Stack of the crash
Crash_calling_Javascript_from_cpp_command_handler.PNG (74.46 KiB) Viewed 5708 times
OneLiner
Techie
 
Posts: 33
Joined: Mon Jan 28, 2019 5:58 am

Re: CppCall upon registered javascript function results in c

Postby ndesktop » Tue Jan 29, 2019 11:01 am

Hard to say just from the picture. It crashes entering the function? This is usually the sign of a bad calling convention, mismatched vtbl pointers etc.
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: CppCall upon registered javascript function results in c

Postby OneLiner » Tue Jan 29, 2019 12:05 pm

Thank you for answering.
But the same function call worked, at the time of registration. ( => With the execution of line B.)14 a messagebox appears. ("Hello From Javascript!"))
So the function call itself seems to be correct, but maybe the javascript-callback has become invalid somehow?
OneLiner
Techie
 
Posts: 33
Joined: Mon Jan 28, 2019 5:58 am

Re: CppCall upon registered javascript function results in c

Postby ndesktop » Tue Jan 29, 2019 2:39 pm

Although my German is a little rusty (read: I'm not 100% sure is this is a stack of the good old Accesso de violaccion or are Kreator lyrics), it is most likely one of the variables self, browser etc. which is invalid.
Jokes aside, try to recapture the crash and look in Debug|Locals, Debug|Watch the variables involved in the call.
Maybe is a simple asycnhronous call done using a stack variable, and when the callback reenters in IO thread the variable is invalid.
Something like

Code: Select all
... call from UI thread
void f() {
CSomeClass obj;
Call(&obj);
// obj is going out of scope here
}

... later in IO thread
void Callback(CSomeClass *obj) {
  obj->DoSomething(); // obj is used here but is destroyed/out of scope/invalidated in UI thread
}
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: CppCall upon registered javascript function results in c

Postby OneLiner » Wed Jan 30, 2019 5:38 am

magreenblatt wrote:Using static members is also a bad idea if you're planning to load multiple pages or frames in your app. For a better pattern see https://bitbucket.org/chromiumembedded/ ... t-bindings


Thank you ndesktop and magreen, this pattern solved the issue.
OneLiner
Techie
 
Posts: 33
Joined: Mon Jan 28, 2019 5:58 am


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 90 guests