Skip to content
Open
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
25 changes: 19 additions & 6 deletions lib/internal/inspector_network_tracking.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
'use strict';

// The network tracking modules are loaded eagerly here, at setup time, rather
// than lazily inside enable()/disable(). enable() can be invoked from an
// inspector interrupt triggered by a `Network.enable` message, which lands in
// the middle of arbitrary JavaScript execution -- including while another
// module is still being loaded by require(). Loading these modules at that
// point (they pull in `inspector`, `worker_threads` and `stream`) can observe
// a half-initialized module and throw, which the inspector agent turns into a
// fatal, unrecoverable error that aborts the process.
// Refs: https://github.com/nodejs/node/issues/64308
const networkHttp = require('internal/inspector/network_http');
const networkHttp2 = require('internal/inspector/network_http2');
const networkUndici = require('internal/inspector/network_undici');

function enable() {
require('internal/inspector/network_http').enable();
require('internal/inspector/network_http2').enable();
require('internal/inspector/network_undici').enable();
networkHttp.enable();
networkHttp2.enable();
networkUndici.enable();
}

function disable() {
require('internal/inspector/network_http').disable();
require('internal/inspector/network_http2').disable();
require('internal/inspector/network_undici').disable();
networkHttp.disable();
networkHttp2.disable();
networkUndici.disable();
}

module.exports = {
Expand Down
43 changes: 43 additions & 0 deletions test/parallel/test-inspector-network-tracking-eager-load.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Flags: --expose-internals --inspect=0 --experimental-network-inspection
'use strict';

// Regression test for https://github.com/nodejs/node/issues/64308.
//
// A `Network.enable` inspector message is dispatched to the main thread via an
// interrupt that can land in the middle of arbitrary JavaScript execution,
// including while another module is still being loaded by require(). If the
// network tracking enable() path lazily require()s its modules (which pull in
// `inspector`, `worker_threads` and `stream`) at that point, it can observe a
// half-initialized module and throw. The inspector agent treats any exception
// thrown while toggling network tracking as an unrecoverable fatal error and
// aborts the whole process.
//
// Guard against a regression by asserting that the network tracking modules
// are loaded eagerly at setup time and that enable()/disable() do not load any
// module themselves.

const common = require('../common');
common.skipIfInspectorDisabled();

const assert = require('assert');
const { enable, disable } = require('internal/inspector_network_tracking');

// With --experimental-network-inspection, the tracking modules must already be
// loaded (they are required at module scope of internal/inspector_network_tracking,
// which itself is loaded during bootstrap when the flag is set).
for (const mod of [
'NativeModule internal/inspector/network_http',
'NativeModule internal/inspector/network_http2',
'NativeModule internal/inspector/network_undici',
]) {
assert(process.moduleLoadList.includes(mod),
`${mod} should be loaded eagerly at setup, but was not`);
}

// enable()/disable() must not trigger any further module loading, so that they
// are safe to run from an inspector interrupt that fires mid-require().
const before = process.moduleLoadList.length;
enable();
disable();
assert.strictEqual(process.moduleLoadList.length, before,
'enable()/disable() must not lazily load any module');
Loading