Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inspector: allow concurrent inspector sessions #20137

Closed
wants to merge 1 commit into from
Closed

inspector: allow concurrent inspector sessions #20137

wants to merge 1 commit into from

Conversation

eugeneo
Copy link
Contributor

@eugeneo eugeneo commented Apr 18, 2018

This change enables concurrent inspector sessions, through WebSocket
interface as well as JS interface, in any combination.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Apr 18, 2018
@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 18, 2018

CI: https://ci.nodejs.org/job/node-test-pull-request/14366/ (note there might be platform-specific issues, I will be looking into them)

@eugeneo eugeneo added the inspector Issues and PRs related to the V8 inspector protocol label Apr 18, 2018
@jasnell
Copy link
Member

jasnell commented Apr 18, 2018

Generally good with this, haven't reviewed the code yet so won't sign off just yet. But, I wanted to ask if you could articulate some of the issues that could present with this. For instance, suppose I have two concurrent sessions open... is it possible for one to interfere with the other? For instance, what impact does setting a breakpoint in one session have on the other? Can there be hidden side effects?

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 18, 2018

@jasnell there are many edge cases, and that is expected...

The main use-case had been to allow different tools use different "domains" concurrently - e.g. some IDE would connect to Chrome for debugging, while Chrome DevTools can still be used to inspect DOM. For Node, this should allow debuginng the application that uses the inspector module.

  1. Breakpoints do not get reported to other frontends, to avoid confusing them.
  2. Pause events are reported to all frontends.
  3. "Debugger.resume" sent by any frontend will resume execution for all.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 18, 2018

Another CI run, I had a bad testcase in the original version: https://ci.nodejs.org/job/node-test-pull-request/14367/

@jasnell
Copy link
Member

jasnell commented Apr 18, 2018

  1. Breakpoints do not get reported to other frontends, to avoid confusing them.
  2. Pause events are reported to all frontends.
  3. "Debugger.resume" sent by any frontend will resume execution for all.

1 and 2 are the concerns for me. What we'll end up with are pauses in one frontend that happens for no obvious reason. What I'd like to make sure of is that when the pause is reported, there is enough context included for one frontend to know that the pause originated in a concurrently connected session so at least there's the ability to reason about it. If that's already accounted for, then awesome, never mind me :-)

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 18, 2018

@jasnell this isn't that different from the debugger statement. Frontends already have to be ready for random pauses.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 18, 2018

Found a bug in V8 inspector around multisession support. Updated this PR with a workaround for a said bug. New CI: https://ci.nodejs.org/job/node-test-pull-request/14373/

@jasnell
Copy link
Member

jasnell commented Apr 18, 2018

@eugeneo ... thank you for the additional detail. As I've said I'm generally good with this I just want to make sure we have a good idea of what issues may come up with this. Any time we get into multi-session anything, especially with single loop, there are bound to be issues ;-) . Thank you for doing this!

Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally LGTM but would love @addaleax and @bnoordhuis to take a look :-)

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 19, 2018

CI for a new version: https://ci.nodejs.org/job/node-test-pull-request/14386/

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 19, 2018

CI mostly green, looks like MacOS CI is busted and failes on all changes. There are no inspector-specific test failures.

new ChannelImpl(client_.get(), delegate));
int connectFrontend(std::unique_ptr<InspectorSessionDelegate> delegate) {
events_dispatched_ = true;
int session_id = next_session_id_++;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for this to have a race condition (e.g. WebSocket server and a JS inspector session launching at the same time)?

Copy link
Contributor Author

@eugeneo eugeneo Apr 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All API in this file are called only from the main thread. E.g. incoming WS session will "interrupt" V8 (or will use uv_async_t) before calling this function.

// There is a bug in inspector that causes every session
// call V8InspectorClient::quitMessageLoopOnPause. We are using this flag
// to ignore those calls so message loop is spinning as long as there's a
// reason to expect inspector messages
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a crbug for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put that link in the comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it in a separate commit, will squash before merging.

Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some suggestions for improvements but LGTM either way.

events_dispatched_ = true;
int session_id = next_session_id_++;
channels_[session_id] =
std::make_unique<ChannelImpl>(client_.get(), std::move(delegate));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

client_.get() looks kind of questionable. Could it be turned into a std::shared_ptr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not want to imply shared ownership. I changed the code to use const std::unique_ptr&.

std::unordered_map<void*, InspectorTimerHandle> timers_;
int next_session_id_;
bool events_dispatched_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool events_dispatched_ = false;?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this and other similar fields.

std::unique_ptr<InspectorSession> Agent::Connect(
std::unique_ptr<InspectorSessionDelegate> delegate) {
int session_id = client_->connectFrontend(std::move(delegate));
return std::make_unique<InspectorSession>(session_id, client_.get());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe turn client_ into a std::shared_ptr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did that.

session->CheckIsCurrent();
Agent* inspector = env->inspector_agent();
inspector->Dispatch(ToProtocolString(env->isolate(), info[0])->string());
if (session->session_)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put braces around the body?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Persistent<Function> callback_;
};

static bool InspectorEnabled(Environment* env) {
Agent* agent = env->inspector_agent();
return !!agent->io() || agent->HasConnectedSessions();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you do an explicit nullptr check instead of coercing to bool?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}, 150);
session.on('Debugger.paused', () => {
session.disconnect();
process.exit(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be infinitesimally nicer to have node exit naturally by calling clearInterval(interval).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 20, 2018

Thank you for the reviews, I addressed the comments.
New CI: https://ci.nodejs.org/job/node-test-pull-request/14405/

I will merge this PR after the weekend.

@Trott
Copy link
Member

Trott commented Apr 20, 2018

Relevant macOS test failure:

https://ci.nodejs.org/job/node-test-commit-osx/17976/nodes=osx1010/console

not ok 1107 parallel/test-inspector-multisession-ws
  ---
  duration_ms: 0.330
  severity: fail
  exitcode: 1
  stack: |-
    [test] Connecting to a child Node process
    [test] Testing /json/list
    [test] Connecting to a child Node process
    [test] Testing /json/list
    [err] Debugger listening on ws://127.0.0.1:50554/d51f55a4-567c-49b0-89cd-669ce131d100
    [err] For help, see: https://nodejs.org/en/docs/inspector
    [err] 
    { Error: write EPIPE
        at WriteWrap.afterWrite [as oncomplete] (net.js:836:14) errno: 'EPIPE', code: 'EPIPE', syscall: 'write' }
    1
  ...

Trott
Trott previously requested changes Apr 21, 2018
Copy link
Member

@Trott Trott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking on the test failure. Feel free to clear this if the test has been fixed.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 24, 2018

Test failure is caused by #20254, I would like to land that PR before landing this one.

This change enables concurrent inspector sessions, through WebSocket
interface as well as JS interface, in any combination.

PR-URL: #20137
@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 26, 2018

Rebased, squashed the commits, CI is green: https://ci.nodejs.org/job/node-test-commit/18054/

@Trott - please take another look.

@ofrobots
Copy link
Contributor

Given this from statement @Trott:

Blocking on the test failure. Feel free to clear this if the test has been fixed.

Since the CI is green now, I think it is reasonable to dismiss that review.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 26, 2018

Landed as 1300103

@eugeneo eugeneo closed this Apr 26, 2018
@addaleax
Copy link
Member

Just got this CI failure for an AIX stress-test run: https://ci.nodejs.org/job/node-stress-single-test/1825/nodes=aix61-ppc64/console

It seems related to this PR? Not sure why it wouldn’t show up in regular CI…

@richardlau
Copy link
Member

Not sure why it wouldn’t show up in regular CI…

I think because the stress job isn't using the compiler selector script added by nodejs/build#1240 so it's using the wrong level of gcc.

cc @nodejs/build @mhdawson

@richardlau
Copy link
Member

e.g., https://ci.nodejs.org/job/node-stress-single-test/1825/nodes=aix61-ppc64/consoleFull

16:38:06 WARNING: C++ compiler too old, need g++ 4.9.4 or clang++ 3.4.2 (CXX=g++)

We should be using gcc 6.3 on AIX for v10.x and master as per nodejs/build#1240.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 27, 2018

Should I remove make_unique or this is old failure and new AIX now uses newer STL?

@richardlau
Copy link
Member

@eugeneo I believe it's an infrastructure issue with the stress job not using the correct level of C++ compiler on AIX (the normal CI jobs should be fine).

This PR is the first change that's actually caused the build to fail on older compilers (where previously you would be warned but the build would succeed), but there's a reason we specify the supported toolchains.

@eugeneo
Copy link
Contributor Author

eugeneo commented Apr 27, 2018

@richardlau Ok, thanks. Ping me if this needs to be fixed - this is a trivial change.

MylesBorins pushed a commit that referenced this pull request May 4, 2018
This change enables concurrent inspector sessions, through WebSocket
interface as well as JS interface, in any combination.

PR-URL: #20137
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@MylesBorins MylesBorins mentioned this pull request May 8, 2018
MarshallOfSound added a commit to electron/electron that referenced this pull request Jun 18, 2018
alexeykuzmin pushed a commit to electron/electron that referenced this pull request Jun 18, 2018
MarshallOfSound added a commit to electron/electron that referenced this pull request Jun 19, 2018
deepak1556 added a commit to electron/electron that referenced this pull request Oct 30, 2018
deepak1556 added a commit to electron/electron that referenced this pull request Nov 9, 2018
deepak1556 added a commit to electron/electron that referenced this pull request Nov 14, 2018
deepak1556 added a commit to electron/electron that referenced this pull request Nov 29, 2018
zcbenz pushed a commit to electron/electron that referenced this pull request Nov 30, 2018
deepak1556 added a commit to electron/electron that referenced this pull request Dec 2, 2018
deepak1556 added a commit to electron/electron that referenced this pull request Dec 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. inspector Issues and PRs related to the V8 inspector protocol lib / src Issues and PRs related to general changes in the lib or src directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants