Skip to content

Commit

Permalink
inspector: libuv notification on incoming message
Browse files Browse the repository at this point in the history
Currently Inspector posts a V8 "task" when a message is incoming. To
make sure messages are processed even when no JS is executed (e.g. while
waiting for I/O or timer), inspector will now post a libuv request.

Fixes: #11589
PR-URL: #11617
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
  • Loading branch information
Eugene Ostroukhov authored and addaleax committed Mar 5, 2017
1 parent 98d3328 commit f972bd8
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 7 deletions.
17 changes: 13 additions & 4 deletions src/inspector_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class AgentImpl {

static void ThreadCbIO(void* agent);
static void WriteCbIO(uv_async_t* async);
static void MainThreadAsyncCb(uv_async_t* req);

void InstallInspectorOnProcess();

Expand Down Expand Up @@ -190,6 +191,7 @@ class AgentImpl {
node::Environment* parent_env_;

uv_async_t io_thread_req_;
uv_async_t main_thread_req_;
V8NodeInspector* inspector_;
v8::Platform* platform_;
MessageQueue<InspectorAction> incoming_message_queue_;
Expand Down Expand Up @@ -334,6 +336,9 @@ AgentImpl::AgentImpl(Environment* env) : delegate_(nullptr),
dispatching_messages_(false),
session_id_(0),
server_(nullptr) {
CHECK_EQ(0, uv_async_init(env->event_loop(), &main_thread_req_,
AgentImpl::MainThreadAsyncCb));
uv_unref(reinterpret_cast<uv_handle_t*>(&main_thread_req_));
CHECK_EQ(0, uv_sem_init(&start_sem_, 0));
memset(&io_thread_req_, 0, sizeof(io_thread_req_));
}
Expand Down Expand Up @@ -416,10 +421,7 @@ bool AgentImpl::Start(v8::Platform* platform, const char* path,

InstallInspectorOnProcess();

int err = uv_loop_init(&child_loop_);
CHECK_EQ(err, 0);

err = uv_thread_create(&thread_, AgentImpl::ThreadCbIO, this);
int err = uv_thread_create(&thread_, AgentImpl::ThreadCbIO, this);
CHECK_EQ(err, 0);
uv_sem_wait(&start_sem_);

Expand Down Expand Up @@ -606,6 +608,7 @@ void AgentImpl::PostIncomingMessage(InspectorAction action, int session_id,
platform_->CallOnForegroundThread(isolate,
new DispatchOnInspectorBackendTask(this));
isolate->RequestInterrupt(InterruptCallback, this);
CHECK_EQ(0, uv_async_send(&main_thread_req_));
}
NotifyMessageReceived();
}
Expand Down Expand Up @@ -662,6 +665,12 @@ void AgentImpl::DispatchMessages() {
dispatching_messages_ = false;
}

// static
void AgentImpl::MainThreadAsyncCb(uv_async_t* req) {
AgentImpl* agent = node::ContainerOf(&AgentImpl::main_thread_req_, req);
agent->DispatchMessages();
}

void AgentImpl::Write(TransportAction action, int session_id,
const StringView& inspector_message) {
AppendMessage(&outgoing_message_queue_, action, session_id,
Expand Down
21 changes: 18 additions & 3 deletions test/inspector/inspector-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,24 @@ Harness.prototype.expectShutDown = function(errorCode) {
});
};

exports.startNodeForInspectorTest = function(callback) {
const child = spawn(process.execPath,
[ '--inspect-brk', mainScript ]);
Harness.prototype.kill = function() {
return this.enqueue_((callback) => {
this.process_.kill();
callback();
});
};

exports.startNodeForInspectorTest = function(callback,
inspectorFlag = '--inspect-brk',
opt_script_contents) {
const args = [inspectorFlag];
if (opt_script_contents) {
args.push('-e', opt_script_contents);
} else {
args.push(mainScript);
}

const child = spawn(process.execPath, args);

const timeoutId = timeout('Child process did not start properly', 4);

Expand Down
20 changes: 20 additions & 0 deletions test/inspector/test-not-blocked-on-idle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';
require('../common');
const helper = require('./inspector-helper.js');

function shouldShutDown(session) {
session
.sendInspectorCommands([
{ 'method': 'Debugger.enable' },
{ 'method': 'Debugger.pause' },
])
.disconnect(true);
}

function runTests(harness) {
// 1 second wait to make sure the inferior began running the script
setTimeout(() => harness.runFrontendSession([shouldShutDown]).kill(), 1000);
}

const script = 'setInterval(() => {debugger;}, 60000);';
helper.startNodeForInspectorTest(runTests, '--inspect', script);

0 comments on commit f972bd8

Please sign in to comment.