Commit 5e893ce0725 for nodejs
commit 5e893ce0725de12d7cb6df79ebb4b6d813648328
Author: Joyee Cheung <joyeec9h3@gmail.com>
Date: Thu Nov 5 16:21:41 2026 +0100
src: do not enable the inspector during snapshot building
V8 no longer allows attaching a debuger or setting a debug context ID
during snapshot building. Avoid enabling the inspector in this case,
and reject the inspector options when the user-land --build-snapshot
is used.
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/8679045
Signed-off-by: Joyee Cheung <joyeec9h3@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/67154
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
diff --git a/doc/api/cli.md b/doc/api/cli.md
index d3309ae6192..415b65ac5ef 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -721,6 +721,10 @@ an additional module during the snapshot building process is needed,
please file a request in the [Node.js issue tracker][] and link to it in the
[tracking issue for user-land snapshots][].
+During snapshot building, a debugger cannot be attached to the process.
+`--build-snapshot` cannot be used together with `--inspect`, `--inspect-brk` or
+`--inspect-wait`.
+
### `--build-snapshot-config`
<!-- YAML
diff --git a/doc/node.1 b/doc/node.1
index 444da29eed3..7419eb9a34d 100644
--- a/doc/node.1
+++ b/doc/node.1
@@ -447,6 +447,9 @@ runtime, using either \fBv8.startupSnapshot.setDeserializeMainFunction()\fR or
an additional module during the snapshot building process is needed,
please file a request in the Node.js issue tracker and link to it in the
tracking issue for user-land snapshots.
+During snapshot building, a debugger cannot be attached to the process.
+\fB--build-snapshot\fR cannot be used together with \fB--inspect\fR, \fB--inspect-brk\fR or
+\fB--inspect-wait\fR.
.
.It Fl -build-snapshot-config
Specifies the path to a JSON configuration file which configures snapshot
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
index 22506e26b32..cfa2f2adb9d 100644
--- a/src/inspector_agent.cc
+++ b/src/inspector_agent.cc
@@ -528,7 +528,11 @@ class NodeInspectorClient : public V8InspectorClient {
is_main_ ? GetHumanReadableProcessName() : GetWorkerLabel(env);
ContextInfo info(name);
info.is_default = true;
- contextCreated(env->context(), info);
+ // V8 does not allow a debugger to be attached while a startup or
+ // a debug context ID to be set during snapshot building.
+ if (!env->isolate_data()->is_building_snapshot()) {
+ contextCreated(env->context(), info);
+ }
}
void runMessageLoopOnPause(int context_group_id) override {
@@ -923,6 +927,12 @@ bool Agent::StartIoThread() {
CHECK_NOT_NULL(client_);
+ if (parent_env_->isolate_data()->is_building_snapshot()) {
+ fprintf(stderr,
+ "The inspector cannot be activated while building a snapshot.\n");
+ return false;
+ }
+
io_ = InspectorIo::Start(client_->getThreadHandle(),
path_,
host_port_,
diff --git a/src/node_options.cc b/src/node_options.cc
index 4ba4801ad1d..e141fab9e82 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -203,23 +203,16 @@ void PerProcessOptions::CheckProcessTimeoutOptions(
// make the timeout fire while the debugger is in control, so the two cannot
// be combined. Runtime activation of the inspector is rejected separately.
const DebugOptions& debug_options = per_isolate->per_env->debug_options();
- const char* debug_option = nullptr;
- if (debug_options.break_node_first_line) {
- debug_option = "--inspect-brk-node";
- } else if (debug_options.break_first_line) {
- debug_option = "--inspect-brk";
- } else if (debug_options.inspect_wait) {
- debug_option = "--inspect-wait";
- } else if (debug_options.inspector_enabled) {
- debug_option = "--inspect";
- } else if (debug_options.host_port.host() != "127.0.0.1" ||
- debug_options.host_port.port() !=
- DebugOptions::kDefaultInspectorPort) {
- // We can't catch the case where the value passed is the default value,
- // then the option just becomes a noop which is fine.
- debug_option = "--inspect-port";
- } else if (debug_options.inspect_publish_uid_string != "stderr,http") {
- debug_option = "--inspect-publish-uid";
+ const char* debug_option = debug_options.inspector_option_name();
+ if (debug_option == nullptr) {
+ if (debug_options.host_port.host() != "127.0.0.1" ||
+ debug_options.host_port.port() != DebugOptions::kDefaultInspectorPort) {
+ // We can't catch the case where the value passed is the default value,
+ // then the option just becomes a noop which is fine.
+ debug_option = "--inspect-port";
+ } else if (debug_options.inspect_publish_uid_string != "stderr,http") {
+ debug_option = "--inspect-publish-uid";
+ }
}
if (debug_option != nullptr) {
errors->push_back(std::string("either --process-timeout or ") +
@@ -297,6 +290,16 @@ void PerIsolateOptions::CheckOptions(std::vector<std::string>* errors,
HandleMaxOldSpaceSizePercentage(errors, &max_old_space_size_percentage);
}
+ if (build_snapshot) {
+ // V8 does not allow a debugger to be attached during snapshot building.
+ const char* debug_option = per_env->debug_options().inspector_option_name();
+ if (debug_option != nullptr) {
+ errors->push_back(
+ std::string("--build-snapshot cannot be used together with ") +
+ debug_option);
+ }
+ }
+
per_env->CheckOptions(errors, argv);
}
diff --git a/src/node_options.h b/src/node_options.h
index f8aa5825386..d28560c5a53 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -112,6 +112,14 @@ class DebugOptions : public Options {
return break_first_line || break_node_first_line;
}
+ const char* inspector_option_name() const {
+ if (break_node_first_line) return "--inspect-brk-node";
+ if (break_first_line) return "--inspect-brk";
+ if (inspect_wait) return "--inspect-wait";
+ if (inspector_enabled) return "--inspect";
+ return nullptr;
+ }
+
void CheckOptions(std::vector<std::string>* errors,
std::vector<std::string>* argv) override;
};
diff --git a/test/parallel/test-inspect-address-in-use.js b/test/parallel/test-inspect-address-in-use.js
index bd954e4a7bc..9c97aeabf3a 100644
--- a/test/parallel/test-inspect-address-in-use.js
+++ b/test/parallel/test-inspect-address-in-use.js
@@ -42,9 +42,14 @@ function testChildProcess(getArgs, exitCode, options) {
tmpdir.refresh();
-testChildProcess(
- (port) => [`--inspect=${port}`, '--build-snapshot', entry], 0,
- { cwd: tmpdir.path });
+// V8 does not allow a debugger to be attached during snapshot building.
+spawnSyncAndExit(process.execPath, ['--inspect=0', '--build-snapshot', entry],
+ { cwd: tmpdir.path },
+ {
+ status: 9,
+ signal: null,
+ stderr: /--build-snapshot cannot be used together with --inspect/,
+ });
testChildProcess(
(port) => [`--inspect=${port}`, entry], 0);
diff --git a/test/parallel/test-snapshot-console.js b/test/parallel/test-snapshot-console.js
index 4acc804b201..b65014da989 100644
--- a/test/parallel/test-snapshot-console.js
+++ b/test/parallel/test-snapshot-console.js
@@ -30,7 +30,10 @@ const entry = fixtures.path('snapshot', 'console.js');
console.log(child.stderr.toString());
assert.strictEqual(child.status, 0);
}
- assert.deepStrictEqual(Object.keys(console), JSON.parse(stdout));
+ // console.createTask is not available during snapshot buildling.
+ assert.deepStrictEqual(
+ Object.keys(console).filter((key) => key !== 'createTask'),
+ JSON.parse(stdout));
const stats = fs.statSync(tmpdir.resolve('snapshot.blob'));
assert(stats.isFile());
}