Is is required to grab v8::Locker when using V8 Debugger?

46 views
Skip to first unread message

Abhishek Singh

unread,
Aug 16, 2016, 7:10:39 AM8/16/16
to v8-u...@googlegroups.com
Hi,

I’m using V8 Debugger, but facing an issue. 

https://gist.github.com/abhi-bit/20b8569bc5d655659b51d425564eb49d - this is link to standalone code simulating the same problem. In short, what this code does is:

* Main thread i.e. the calling JS code with required params periodically. Given it’s Local<Function> Call, I’m using V8::Locker(without it handlescope errors out asking me to use locking api)
* Debug thread, that basically sets breakpoint -> list breakpoints and finally clears the breakpoints in that order(with some sleep pause in between the call), this too is using Locker and hence leading to the problem I’m facing.

In the given test case, main thread keeps running for first 10 secs and doesn’t let Debug thread to proceed(because main thread has a lock for the isolate) - so essentially I can’t do debug operations from another thread. How can I avoid using locker in either main and debug threads or both and debug user supplied JS code at runtime? Looking at v8 debug unit tests, I don’t see it using locker anywhere in there. 

Thanks,
Abhishek

Ben Noordhuis

unread,
Aug 16, 2016, 9:50:15 AM8/16/16
to v8-users
Your threads should not sleep while holding the Locker. Let it go out
of scope before calling this_thread::sleep_for().

You could create a v8::Unlocker instance but you need to exit the
Context scope first so letting the Locker go out of scope is probably
just as easy.

Abhishek Singh

unread,
Aug 16, 2016, 12:22:48 PM8/16/16
to v8-u...@googlegroups.com
Hi Ben,

In sample example I shared, I was trying to simulate a behaviour similar to what my application(based on top of V8) saw - sleep calls were added to somehow make this example artificially simulate the app. I’ve modified the gist, hoping now it doesn’t create confusion.

Here is sample output from it, I’ll explain below what they mean(annotating by line no to make it easy to explain, otherwise would need ascii drawing :)):

line# Output Message
====================================
1 debugger.ccTestBreakPoints179
2 debugger.ccTestBreakPoints181
3 debugger.ccSendDebugUserRequest146
4 2016-08-16.21:33:16 DebugSetBreakpointHandler {"seq":0,"request_seq":1,"type":"response","command":"setbreakpoint","success":true,"body":{"type":"scriptId","breakpoint":1,"script_id":33,"line":1,"column":0,"actual_locations”: [{"line":1,"column":4,"script_id":33}]},"refs":[],"running":true}
5 2016-08-16.21:33:18 DebugListBreakpointHandler {"seq":1,"request_seq":3,"type":"response","command":"listbreakpoints","success":true,"body":{"breakpoints":[{"number":1,"line":1,"column":0,"groupId":null,"active":true,"condition":null,"actual_locations":[{"line":1,"column":4,"script_id":33}],"type":"scriptId","script_id":33}],"breakOnExceptions":false,"breakOnUncaughtExceptions":false},"refs":[],"running":true}
6 debugger.ccSendDebugUserRequest148
7 2016-08-16.21:33:18SendDebugUserRequest{"type": "json", "client": "Chrome Canary", "counter":0}
8 debugger.ccSendDebugUserRequest162
9 2016-08-16.21:33:18 DebugListBreakpointHandler {"seq":2,"type":"event","event":"break","body":{"invocationText":"DebugUserRequest(doc=#<Object>)","sourceLine":1,"sourceColumn":4,"sourceLineText":" if (doc.type === \"json\") {","script":{"id":33,"name":null,"lineOffset":0,"columnOffset":0,"lineCount":6},"breakpoints":[1]}}
10 debugger.ccTestClearBreakPoints208

<Execution stuck beyond this point>

Line 1-2,4, 5 - basically setup breakpoint and lists them
Line 3,6,7-9 - trying to call the user supplied JS code but it doesn’t proceed to finish execution because it’s waiting at the breakpoint set earlier - hoping someone would fire continue/clearbreakpoint
Line 10 - Attempt to clear breakpoint but this guy can’t proceed further because the user supplied code(currently stuck at breakpoint) is holding the lock to the isolate

So my question is, how can the user supplied code execution could proceed further in this case?
> --
> --
> v8-users mailing list
> v8-u...@googlegroups.com
> http://groups.google.com/group/v8-users
> ---
> You received this message because you are subscribed to the Google Groups "v8-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Ben Noordhuis

unread,
Aug 17, 2016, 8:13:27 AM8/17/16
to v8-users
On Tue, Aug 16, 2016 at 6:22 PM, Abhishek Singh
<singhabh...@gmail.com> wrote:
> Hi Ben,
>
> In sample example I shared, I was trying to simulate a behaviour similar to what my application(based on top of V8) saw - sleep calls were added to somehow make this example artificially simulate the app. I’ve modified the gist, hoping now it doesn’t create confusion.
>
> Here is sample output from it, I’ll explain below what they mean(annotating by line no to make it easy to explain, otherwise would need ascii drawing :)):
>
> line# Output Message
> ====================================
> 1 debugger.ccTestBreakPoints179
> 2 debugger.ccTestBreakPoints181
> 3 debugger.ccSendDebugUserRequest146
> 4 2016-08-16.21:33:16 DebugSetBreakpointHandler {"seq":0,"request_seq":1,"type":"response","command":"setbreakpoint","success":true,"body":{"type":"scriptId","breakpoint":1,"script_id":33,"line":1,"column":0,"actual_locations”: [{"line":1,"column":4,"script_id":33}]},"refs":[],"running":true}
> 5 2016-08-16.21:33:18 DebugListBreakpointHandler {"seq":1,"request_seq":3,"type":"response","command":"listbreakpoints","success":true,"body":{"breakpoints":[{"number":1,"line":1,"column":0,"groupId":null,"active":true,"condition":null,"actual_locations":[{"line":1,"column":4,"script_id":33}],"type":"scriptId","script_id":33}],"breakOnExceptions":false,"breakOnUncaughtExceptions":false},"refs":[],"running":true}
> 6 debugger.ccSendDebugUserRequest148
> 7 2016-08-16.21:33:18SendDebugUserRequest{"type": "json", "client": "Chrome Canary", "counter":0}
> 8 debugger.ccSendDebugUserRequest162
> 9 2016-08-16.21:33:18 DebugListBreakpointHandler {"seq":2,"type":"event","event":"break","body":{"invocationText":"DebugUserRequest(doc=#<Object>)","sourceLine":1,"sourceColumn":4,"sourceLineText":" if (doc.type === \"json\") {","script":{"id":33,"name":null,"lineOffset":0,"columnOffset":0,"lineCount":6},"breakpoints":[1]}}
> 10 debugger.ccTestClearBreakPoints208
>
> <Execution stuck beyond this point>
>
> Line 1-2,4, 5 - basically setup breakpoint and lists them
> Line 3,6,7-9 - trying to call the user supplied JS code but it doesn’t proceed to finish execution because it’s waiting at the breakpoint set earlier - hoping someone would fire continue/clearbreakpoint
> Line 10 - Attempt to clear breakpoint but this guy can’t proceed further because the user supplied code(currently stuck at breakpoint) is holding the lock to the isolate
>
> So my question is, how can the user supplied code execution could proceed further in this case?

I think I understand what you mean. It sounds like you should be
using v8::Debug::SendCommand() from the second thread, without
grabbing the Locker or changing the debug listener first.

Abhishek Singh

unread,
Aug 17, 2016, 10:51:48 AM8/17/16
to v8-u...@googlegroups.com
Hi Ben,
Basically I’m trying to provide an IDE support for JS in the bundled product, so IDE would never know when “clearbreakpoint" or “continue” request is going to come. So when a “setbreakpoint” command is fired, I need to point the MessageHandler, SendCommand and ProcessDebugMessage & finally give up the Locker. I can’t hold up Locker from second thread(which I assume you referred to set_break_point thread). Please correct me if my assumption is wrong.


> without
> grabbing the Locker or changing the debug listener first.

Till now, I’ve been doing hit and trail for different combinations to avoid Locker - but I’ve never been able to run various debug command request handler without grabbing Locker. But I see v8 test-debug.cc in all places is testing debug apis without using Locker at all. Sorry I don’t know how to run handler code without grabbing Locker, when you’ve some time could you please comment on gist on what possibly I’m missing?

About “changing the debug listener first” - I didn’t get what you mean. Could you give hints on what specific changes you meant?

Given you mentioned 3 different approaches that could help solve my current issue(based on whatever explanation I was able to relay), I’m hoping one of them would apply to my use case.

Ben Noordhuis

unread,
Aug 17, 2016, 1:39:49 PM8/17/16
to v8-users
On Wed, Aug 17, 2016 at 4:51 PM, Abhishek Singh
In your gist, you call v8::Debug::SetMessageHandler() in a couple of
places. I'd change that to once at start-up so you don't need to grab
the Locker when you want to send a message - you don't need it for
v8::Debug::SendCommand().

Abhishek Singh

unread,
Aug 22, 2016, 1:53:32 AM8/22/16
to v8-u...@googlegroups.com
Modified the test program, link https://gist.github.com/abhi-bit/20b8569bc5d655659b51d425564eb49d - debug calls are now executing without grabbing Locker.

Problem I see right now, is with following flow of events:

User JS code running -> BreakPoint set -> ListBreakPoint call -> ClearBreakPoint Call -> User JS code execution resume - In above test code User JS code execution doesn’t resume. It appears for calling Debug::ProcessDebugMessages(), Locker is required hence calling it while executing JS code with required arguments - I think that’s a problem leading to user code execution being stuck at breakpoint. Suggestions please?

Abhishek Singh

unread,
Aug 22, 2016, 6:24:03 AM8/22/16
to v8-u...@googlegroups.com
nvm, solved it. Thanks for help thus far.
Reply all
Reply to author
Forward
0 new messages