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

src: skip inspector wait in internal workers #54219

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/api/environment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,8 @@ IsolateData* CreateIsolateData(
MultiIsolatePlatform* platform,
ArrayBufferAllocator* allocator,
const EmbedderSnapshotData* embedder_snapshot_data) {
const SnapshotData* snapshot_data =
SnapshotData::FromEmbedderWrapper(embedder_snapshot_data);
return new IsolateData(isolate, loop, platform, allocator, snapshot_data);
return IsolateData::CreateIsolateData(
isolate, loop, platform, allocator, embedder_snapshot_data);
}

void FreeIsolateData(IsolateData* isolate_data) {
Expand Down
5 changes: 0 additions & 5 deletions src/env-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,11 +590,6 @@ inline std::shared_ptr<PerIsolateOptions> IsolateData::options() {
return options_;
}

inline void IsolateData::set_options(
std::shared_ptr<PerIsolateOptions> options) {
options_ = std::move(options);
}

template <typename Fn>
void Environment::SetImmediate(Fn&& cb, CallbackFlags::Flags flags) {
auto callback = native_immediates_.CreateCallback(std::move(cb), flags);
Expand Down
24 changes: 20 additions & 4 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -538,19 +538,35 @@ Mutex IsolateData::isolate_data_mutex_;
std::unordered_map<uint16_t, std::unique_ptr<PerIsolateWrapperData>>
IsolateData::wrapper_data_map_;

IsolateData* IsolateData::CreateIsolateData(
Isolate* isolate,
uv_loop_t* loop,
MultiIsolatePlatform* platform,
ArrayBufferAllocator* allocator,
const EmbedderSnapshotData* embedder_snapshot_data,
std::shared_ptr<PerIsolateOptions> options) {
const SnapshotData* snapshot_data =
SnapshotData::FromEmbedderWrapper(embedder_snapshot_data);
if (options == nullptr) {
options = per_process::cli_options->per_isolate->Clone();
}
return new IsolateData(
isolate, loop, platform, allocator, snapshot_data, options);
}

IsolateData::IsolateData(Isolate* isolate,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform,
ArrayBufferAllocator* node_allocator,
const SnapshotData* snapshot_data)
const SnapshotData* snapshot_data,
std::shared_ptr<PerIsolateOptions> options)
: isolate_(isolate),
event_loop_(event_loop),
node_allocator_(node_allocator == nullptr ? nullptr
: node_allocator->GetImpl()),
platform_(platform),
snapshot_data_(snapshot_data) {
options_.reset(
new PerIsolateOptions(*(per_process::cli_options->per_isolate)));
snapshot_data_(snapshot_data),
options_(std::move(options)) {
v8::CppHeap* cpp_heap = isolate->GetCppHeap();

uint16_t cppgc_id = kDefaultCppGCEmbedderID;
Expand Down
19 changes: 14 additions & 5 deletions src/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,22 @@ struct PerIsolateWrapperData {
};

class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
public:
private:
IsolateData(v8::Isolate* isolate,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform = nullptr,
ArrayBufferAllocator* node_allocator = nullptr,
const SnapshotData* snapshot_data = nullptr);
MultiIsolatePlatform* platform,
ArrayBufferAllocator* node_allocator,
const SnapshotData* snapshot_data,
std::shared_ptr<PerIsolateOptions> options);

public:
static IsolateData* CreateIsolateData(
v8::Isolate* isolate,
uv_loop_t* event_loop,
MultiIsolatePlatform* platform = nullptr,
ArrayBufferAllocator* node_allocator = nullptr,
const EmbedderSnapshotData* embedder_snapshot_data = nullptr,
std::shared_ptr<PerIsolateOptions> options = nullptr);
~IsolateData();

SET_MEMORY_INFO_NAME(IsolateData)
Expand Down Expand Up @@ -173,7 +183,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
inline MultiIsolatePlatform* platform() const;
inline const SnapshotData* snapshot_data() const;
inline std::shared_ptr<PerIsolateOptions> options();
inline void set_options(std::shared_ptr<PerIsolateOptions> options);

inline NodeArrayBufferAllocator* node_allocator() const;

Expand Down
7 changes: 7 additions & 0 deletions src/node_options-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ EnvironmentOptions* PerIsolateOptions::get_per_env_options() {
return per_env.get();
}

std::shared_ptr<PerIsolateOptions> PerIsolateOptions::Clone() const {
auto options =
std::shared_ptr<PerIsolateOptions>(new PerIsolateOptions(*this));
options->per_env = std::make_shared<EnvironmentOptions>(*per_env);
return options;
}

namespace options_parser {

template <typename Options>
Expand Down
13 changes: 13 additions & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ class DebugOptions : public Options {
break_first_line = true;
}

void DisableWaitOrBreakFirstLine() {
inspect_wait = false;
break_first_line = false;
}

bool wait_for_connect() const {
return break_first_line || break_node_first_line || inspect_wait;
}
Expand Down Expand Up @@ -251,6 +256,9 @@ class EnvironmentOptions : public Options {

class PerIsolateOptions : public Options {
public:
PerIsolateOptions() = default;
PerIsolateOptions(PerIsolateOptions&&) = default;

std::shared_ptr<EnvironmentOptions> per_env { new EnvironmentOptions() };
bool track_heap_objects = false;
bool report_uncaught_exception = false;
Expand All @@ -262,6 +270,11 @@ class PerIsolateOptions : public Options {
inline EnvironmentOptions* get_per_env_options();
void CheckOptions(std::vector<std::string>* errors,
std::vector<std::string>* argv) override;

inline std::shared_ptr<PerIsolateOptions> Clone() const;

private:
PerIsolateOptions(const PerIsolateOptions&) = default;
};

class PerProcessOptions : public Options {
Expand Down
32 changes: 21 additions & 11 deletions src/node_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,15 @@ class WorkerThreadData {
isolate->SetStackLimit(w->stack_base_);

HandleScope handle_scope(isolate);
isolate_data_.reset(
CreateIsolateData(isolate,
&loop_,
w_->platform_,
allocator.get(),
w->snapshot_data()->AsEmbedderWrapper().get()));
isolate_data_.reset(IsolateData::CreateIsolateData(
isolate,
&loop_,
w_->platform_,
allocator.get(),
w->snapshot_data()->AsEmbedderWrapper().get(),
std::move(w_->per_isolate_opts_)));
CHECK(isolate_data_);
CHECK(!isolate_data_->is_building_snapshot());
if (w_->per_isolate_opts_)
isolate_data_->set_options(std::move(w_->per_isolate_opts_));
isolate_data_->set_worker_context(w_);
isolate_data_->max_young_gen_size =
params.constraints.max_young_generation_size_in_bytes();
Expand Down Expand Up @@ -491,9 +490,8 @@ Worker::~Worker() {

void Worker::New(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
auto is_internal = args[5];
CHECK(is_internal->IsBoolean());
if (is_internal->IsFalse()) {
bool is_internal = args[5]->IsTrue();
if (!is_internal) {
THROW_IF_INSUFFICIENT_PERMISSIONS(
env, permission::PermissionScope::kWorkerThreads, "");
}
Expand Down Expand Up @@ -658,7 +656,19 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
return;
}
} else {
// Copy the parent's execArgv.
exec_argv_out = env->exec_argv();
per_isolate_opts = env->isolate_data()->options()->Clone();
}

// Internal workers should not wait for inspector frontend to connect or
// break on the first line of internal scripts. Module loader threads are
// essential to load user codes and must not be blocked by the inspector
// for internal scripts.
// Still, `--inspect-node` can break on the first line of internal scripts.
if (is_internal) {
per_isolate_opts->per_env->get_debug_options()
->DisableWaitOrBreakFirstLine();
}

const SnapshotData* snapshot_data = env->isolate_data()->snapshot_data();
Expand Down
4 changes: 4 additions & 0 deletions test/common/inspector-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ class InspectorSession {
return notification.method === 'Runtime.executionContextDestroyed' &&
notification.params.executionContextId === 1;
});
await this.waitForDisconnect();
}

async waitForDisconnect() {
while ((await this._instance.nextStderrString()) !==
'Waiting for the debugger to disconnect...');
await this.disconnect();
Expand Down
34 changes: 34 additions & 0 deletions test/parallel/test-esm-loader-hooks-inspect-brk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This tests esm loader's internal worker will not be blocked by --inspect-brk.
// Regression: https://github.com/nodejs/node/issues/53681

'use strict';
const common = require('../common');

common.skipIfInspectorDisabled();

const assert = require('assert');
const fixtures = require('../common/fixtures');
const { NodeInstance } = require('../common/inspector-helper.js');

async function runIfWaitingForDebugger(session) {
const commands = [
{ 'method': 'Runtime.enable' },
{ 'method': 'Debugger.enable' },
{ 'method': 'Runtime.runIfWaitingForDebugger' },
];

await session.send(commands);
await session.waitForNotification('Debugger.paused');
}

async function runTest() {
const main = fixtures.path('es-module-loaders', 'register-loader.mjs');
const child = new NodeInstance(['--inspect-brk=0'], '', main);

const session = await child.connectInspectorSession();
await runIfWaitingForDebugger(session);
await session.runToCompletion();
assert.strictEqual((await child.expectShutdown()).exitCode, 0);
}

runTest();
33 changes: 33 additions & 0 deletions test/parallel/test-esm-loader-hooks-inspect-wait.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// This tests esm loader's internal worker will not be blocked by --inspect-wait.
// Regression: https://github.com/nodejs/node/issues/53681

'use strict';
const common = require('../common');

common.skipIfInspectorDisabled();

const assert = require('assert');
const fixtures = require('../common/fixtures');
const { NodeInstance } = require('../common/inspector-helper.js');

async function runIfWaitingForDebugger(session) {
const commands = [
{ 'method': 'Runtime.enable' },
{ 'method': 'Debugger.enable' },
{ 'method': 'Runtime.runIfWaitingForDebugger' },
];

await session.send(commands);
}

async function runTest() {
const main = fixtures.path('es-module-loaders', 'register-loader.mjs');
const child = new NodeInstance(['--inspect-wait=0'], '', main);

const session = await child.connectInspectorSession();
await runIfWaitingForDebugger(session);
await session.waitForDisconnect();
assert.strictEqual((await child.expectShutdown()).exitCode, 0);
}

runTest();
Loading