How to capture JavaScript callstack from C++

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.

How to capture JavaScript callstack from C++

Postby gbaltare » Tue Sep 03, 2019 3:00 pm

Hello,

In short:
Is there a way from C++ to capture a CEF3 browser's JavaScript callstack?
I see such is provided in ::OnUncaughtException, but I don't see a way to generate such a stack as part of a C++ request.


More details:
I'm attempting to diagnose an issue (or some similar issues) where a web application hosted in a CEF browser appears to become unresponsive. Sometimes it also displaying a white screen when the application becomes unresponsive. During this issue there is a second simultaneous web application hosted in a CEF browser on a different screen on the same machine that remains responsive.

During this unresponsive period CefCallback's Success method is invoked to transmit data to the unresponsive web application, however there is no logging indicating it was received in the web application.

So I've some suspicion that the unresponsive web application's thread is occupied, perhaps by an infinite loop, and so it cannot respond to the user's requests nor the CefCallback Success invocation. I understand that such infinite loops can be diagnosed by having devtools open and selecting to pause the application once the infinite loop occurs. However as this is an infrequent issue, pausing the application with devtools has not been possible, and in general it would be good to have a more robust approach to capture what the web application is doing when it enters an infinite loop.

That said, I'm not entirely convinced the issue is caused by an infinite loop as from the problem's logs I can see that the C++ is able to navigate the browser, at which point it seems to become responsive again. I do not observe this when I forcibly create an infinite loop, instead I see that the request to navigate the browser occurs but the web app never becomes responsive. (I've read this thread viewtopic.php?f=6&t=4120 about recovering from an infinite loop which similarly suggests that an infinite loop would require the render process to be terminated to recover.)

We are also trying to disable hardware acceleration to see if it resolves the issue as I understand there is some correlation between white screens and hardware acceleration.

This problem is being observed with CEF3.3.3396.1779. I've created the infinite loop hang on that same version, but also CEF3.3.3683.1920.

I see the following log lines generated by CEF with CEF logging at ERROR level, but none of this seems to occur around the time of the problem:
- Many log lines like: [0821/111335.604:WARNING:dns_config_service_win.cc(669)] Failed to read DnsConfig.
- Some log lines like: [0821/110345.102:ERROR:network_change_notifier_win.cc(157)] WSALookupServiceBegin failed with: 1722
- Some log lines like: [0821/121343.902:ERROR:browser_gpu_channel_host_factory.cc(119)] Failed to launch GPU process.
- Some log lines like: [0821/152223.885:WARNING:ipc_message_attachment_set.cc(49)] MessageAttachmentSet destroyed with unconsumed attachments: 0/1
- Some log lines like: [0822/143918.739:ERROR:dns_config_service_win.cc(755)] DNS config watch failed.

In summary:
- Can a JavaScript callstack be generated from a C++ call to help diagnose where the JavaScript might be stuck?
- Are there other suggestions on how to diagnose a hung web application?
- Any other ideas on what the cause of the issue might be, if it is indeed not a infinite loop?

Many thanks,
Grant Baltare
gbaltare
Newbie
 
Posts: 9
Joined: Thu Jan 15, 2015 1:18 pm

Re: How to capture JavaScript callstack from C++

Postby magreenblatt » Tue Sep 03, 2019 3:05 pm

Have you tried using DevTools to inspect the hung renderer? You could also attach a native debugger to the hung process and break using that.
magreenblatt
Site Admin
 
Posts: 12406
Joined: Fri May 29, 2009 6:57 pm

Re: How to capture JavaScript callstack from C++

Postby gbaltare » Thu Sep 05, 2019 8:29 am

Thanks for the reply.

Regarding using DevTools: Unfortunately it seems that DevTools must be opened before the hang. Since the issue has been infrequent this has not been possible.

Regarding using a native debugger: I did attempt to do this (after introducing a purposeful infinite loop) to try to understand if this (or a similar dmp of the renderer process) would help diagnose the issue, as it was not clear to me how possible or easy it would be to understand the current JavaScript callstack from a debugged renderer. I wasn't able to see much but perhaps that was because I did not have CEF symbols loaded. I will try harder to get CEF symbols and debug the test hung renderer process to understand what diagnostic information this yields.


Aside: Firefox seems to have an interesting/helpful behaviour in such an infinite loop scenario. It gives the user an option to stop the infinite loop and if selected will generate a callstack error to console. This would be very useful if we had such in CEF, more so if busy JavaScript thread could be ended in a more programmatic manner.

Thanks again,
Grant
gbaltare
Newbie
 
Posts: 9
Joined: Thu Jan 15, 2015 1:18 pm

Re: How to capture JavaScript callstack from C++

Postby gbaltare » Thu Sep 05, 2019 11:59 am

I've since retrieved the CEF symbols (CEF3.3.3396.1779) and utilized them while debugging the renderer process executing an intentionally introduced infinite loop.

I think I see the main thread executing the infinite JavaScript loop. The top calls of the main thread stack don't point to any CEF C++ code, and the visual studio debugger indicates they are in an unknown language. I can see the disassembly, but that is not very understandable.

Is there some way I can get more information about the current JavaScript call stack from the debugger?

That is I see something like the following on the callstack of the main renderer thread:
Code: Select all
// The first entry is the code location, the second is the language. There are many more Unknown language items above this point omitted for clarity.
...
    5bb0cb1d()   Unknown
    5bb108a4()   Unknown
    5bb0bd31()   Unknown
    libcef.dll!v8::internal::`anonymous namespace'::Invoke(v8::internal::Isolate * isolate, bool is_construct, v8::internal::Handle<v8::internal::Object> target, v8::internal::Handle<v8::internal::Object> receiver, int argc, v8::internal::Handle<v8::internal::Object> * args, v8::internal::Handle<v8::internal::Object> new_target, v8::internal::Execution::MessageHandling message_handling, v8::internal::Execution::Target execution_target) Line 155   C++
    libcef.dll!v8::internal::Execution::Call(v8::internal::Isolate * isolate, v8::internal::Handle<v8::internal::Object> callable, v8::internal::Handle<v8::internal::Object> receiver, int argc, v8::internal::Handle<v8::internal::Object> * argv) Line 202   C++
...
gbaltare
Newbie
 
Posts: 9
Joined: Thu Jan 15, 2015 1:18 pm

Re: How to capture JavaScript callstack from C++

Postby magreenblatt » Thu Sep 05, 2019 12:07 pm

gbaltare wrote:IIs there some way I can get more information about the current JavaScript call stack from the debugger?

I'm not aware of a way to do that, but you can try asking on a support channel for V8 (dev mailing list, etc).
magreenblatt
Site Admin
 
Posts: 12406
Joined: Fri May 29, 2009 6:57 pm


Return to Support Forum

Who is online

Users browsing this forum: Google [Bot], leeroy and 38 guests