From f2f8a6d9216375950580f38a71c5d66ea6f1a5aa Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 2 Sep 2026 22:34:45 +0000 Subject: [PATCH] trace_events: fix abort when Node.js does not own the V8 platform Requiring `node:trace_events` and calling `createTracing()` aborted the process, and `getEnabledCategories()` dereferenced a null pointer, when Node.js runs on an embedder's own platform (`kNoInitializeNodeV8Platform`): no `tracing::Agent` exists then, and `lib/trace_events.js` only checked the compile-time `hasTracing` flag and `ownsProcessState` before handing the null agent to the binding. Have the binding report whether an agent exists and throw the existing `ERR_TRACE_EVENTS_UNAVAILABLE` when it does not, as for a `--without-v8-platform` build. Refs: https://github.com/nodejs/node/pull/19803 Signed-off-by: Shelley Vohr --- doc/api/errors.md | 3 ++- lib/trace_events.js | 8 ++++++-- src/node_trace_events.cc | 6 ++++++ .../test-embedding-trace-events-unavailable.js | 18 ++++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 test/embedding/test-embedding-trace-events-unavailable.js diff --git a/doc/api/errors.md b/doc/api/errors.md index f54ba1d9058c..458f7013b6a3 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -3381,7 +3381,8 @@ category. ### `ERR_TRACE_EVENTS_UNAVAILABLE` The `node:trace_events` module could not be loaded because Node.js was compiled -with the `--without-v8-platform` flag. +with the `--without-v8-platform` flag, or because the process was initialized by +an embedder that provides its own V8 platform. diff --git a/lib/trace_events.js b/lib/trace_events.js index b4b9be242737..c3645de66982 100644 --- a/lib/trace_events.js +++ b/lib/trace_events.js @@ -15,10 +15,14 @@ const { } = require('internal/errors').codes; const { ownsProcessState } = require('internal/worker'); -if (!hasTracing || !ownsProcessState) +const { + CategorySet, + getEnabledCategories, + hasAgent, +} = internalBinding('trace_events'); +if (!hasTracing || !ownsProcessState || !hasAgent()) throw new ERR_TRACE_EVENTS_UNAVAILABLE(); -const { CategorySet, getEnabledCategories } = internalBinding('trace_events'); const { customInspectSymbol } = require('internal/util'); const { format } = require('internal/util/inspect'); const { diff --git a/src/node_trace_events.cc b/src/node_trace_events.cc index db0a37b85e13..5bddd7413e54 100644 --- a/src/node_trace_events.cc +++ b/src/node_trace_events.cc @@ -113,6 +113,10 @@ void NodeCategorySet::Disable(const FunctionCallbackInfo& args) { } } +static void HasAgent(const FunctionCallbackInfo& args) { + args.GetReturnValue().Set(tracing::Agent::GetInstance() != nullptr); +} + void GetEnabledCategories(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); std::string categories = @@ -162,6 +166,7 @@ void NodeCategorySet::Initialize(Local target, Environment* env = Environment::GetCurrent(context); Isolate* isolate = env->isolate(); + SetMethod(context, target, "hasAgent", HasAgent); SetMethod(context, target, "getEnabledCategories", GetEnabledCategories); SetMethod(context, target, @@ -203,6 +208,7 @@ void NodeCategorySet::Initialize(Local target, void NodeCategorySet::RegisterExternalReferences( ExternalReferenceRegistry* registry) { + registry->Register(HasAgent); registry->Register(GetEnabledCategories); registry->Register(SetTraceCategoryStateUpdateHandler); registry->Register(GetCategoryEnabledBuffer); diff --git a/test/embedding/test-embedding-trace-events-unavailable.js b/test/embedding/test-embedding-trace-events-unavailable.js new file mode 100644 index 000000000000..974702374832 --- /dev/null +++ b/test/embedding/test-embedding-trace-events-unavailable.js @@ -0,0 +1,18 @@ +'use strict'; + +// The embedtest binary runs on its own MultiIsolatePlatform without Node's +// tracing agent, so node:trace_events must report itself as unavailable. + +const common = require('../common'); +const { spawnSyncAndAssert } = require('../common/child_process'); + +spawnSyncAndAssert( + common.resolveBuiltBinary('embedtest'), + [ + 'try { require("node:trace_events").createTracing({ categories: ["v8"] }); }' + + 'catch (e) { console.log(e.code); }', + ], + { + trim: true, + stdout: 'ERR_TRACE_EVENTS_UNAVAILABLE', + });