inspector: libuv notification on incoming message
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: https://github.com/nodejs/node/issues/11589 PR-URL: https://github.com/nodejs/node/pull/11617 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
parent
4cb9f4fde4
commit
f01fd2ae70
@ -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();
|
||||
|
||||
@ -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_;
|
||||
@ -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_));
|
||||
}
|
||||
@ -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_);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
20
test/inspector/test-not-blocked-on-idle.js
Normal file
20
test/inspector/test-not-blocked-on-idle.js
Normal file
@ -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);
|
Loading…
x
Reference in New Issue
Block a user