Skip to content

Commit

Permalink
lib: explicitly initialize debuglog during bootstrap
Browse files Browse the repository at this point in the history
This patch splits the implementation of util.debuglog into a
separate file and explicitly initialize it during pre-execution
since the initialization depends on environment variables.
Also delays the call to `debuglog` in modules that are loaded during
bootstrap to make sure we only access the environment variable
during pre-execution.

PR-URL: nodejs#26468
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
joyeecheung committed Mar 8, 2019
1 parent 687f304 commit b05fd4b
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 46 deletions.
11 changes: 9 additions & 2 deletions lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,15 @@ Readable.ReadableState = ReadableState;
const EE = require('events');
const Stream = require('stream');
const { Buffer } = require('buffer');
const util = require('util');
const debug = util.debuglog('stream');

let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('stream');
}
debuglog(...args);
}

const BufferList = require('internal/streams/buffer_list');
const destroyImpl = require('internal/streams/destroy');
const { getHighWaterMark } = require('internal/streams/state');
Expand Down
7 changes: 7 additions & 0 deletions lib/internal/bootstrap/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ function prepareMainThreadExecution() {
setupCoverageHooks(process.env.NODE_V8_COVERAGE);
}

setupDebugEnv();

// Only main thread receives signals.
setupSignalHandlers();

Expand Down Expand Up @@ -91,6 +93,10 @@ function initializeReport() {
});
}

function setupDebugEnv() {
require('internal/util/debuglog').initializeDebugEnv(process.env.NODE_DEBUG);
}

function setupSignalHandlers() {
const {
createSignalHandlers
Expand Down Expand Up @@ -286,6 +292,7 @@ function loadPreloadModules() {
module.exports = {
setupCoverageHooks,
setupWarningHandler,
setupDebugEnv,
prepareMainThreadExecution,
initializeDeprecations,
initializeESMLoader,
Expand Down
4 changes: 4 additions & 0 deletions lib/internal/main/worker_thread.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
const {
setupCoverageHooks,
setupWarningHandler,
setupDebugEnv,
initializeDeprecations,
initializeESMLoader,
initializeFrozenIntrinsics,
Expand Down Expand Up @@ -39,6 +40,9 @@ const {
} = require('internal/process/execution');

const publicWorker = require('worker_threads');

setupDebugEnv();

const debug = require('util').debuglog('worker');

setupWarningHandler();
Expand Down
8 changes: 7 additions & 1 deletion lib/internal/modules/cjs/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,13 @@ Object.defineProperty(Module, 'wrapper', {
}
});

const debug = util.debuglog('module');
let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('module');
}
debuglog(...args);
}

Module._debug = util.deprecate(debug, 'Module._debug is deprecated.',
'DEP0077');
Expand Down
54 changes: 54 additions & 0 deletions lib/internal/util/debuglog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

const { format } = require('internal/util/inspect');

// `debugs` is deliberately initialized to undefined so any call to
// debuglog() before initializeDebugEnv() is called will throw.
let debugs;

let debugEnvRegex = /^$/;

// `debugEnv` is initial value of process.env.NODE_DEBUG
function initializeDebugEnv(debugEnv) {
debugs = {};
if (debugEnv) {
debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
.replace(/\*/g, '.*')
.replace(/,/g, '$|^')
.toUpperCase();
debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i');
}
}

// Emits warning when user sets
// NODE_DEBUG=http or NODE_DEBUG=http2.
function emitWarningIfNeeded(set) {
if ('HTTP' === set || 'HTTP2' === set) {
process.emitWarning('Setting the NODE_DEBUG environment variable ' +
'to \'' + set.toLowerCase() + '\' can expose sensitive ' +
'data (such as passwords, tokens and authentication headers) ' +
'in the resulting log.');
}
}

function debuglog(set) {
set = set.toUpperCase();
if (!debugs[set]) {
if (debugEnvRegex.test(set)) {
const pid = process.pid;
emitWarningIfNeeded(set);
debugs[set] = function debug(...args) {
const msg = format(...args);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function debug() {};
}
}
return debugs[set];
}

module.exports = {
debuglog,
initializeDebugEnv
};
10 changes: 8 additions & 2 deletions lib/internal/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const EventEmitter = require('events');
const assert = require('internal/assert');
const path = require('path');
const util = require('util');

const {
ERR_WORKER_PATH,
ERR_WORKER_UNSERIALIZABLE_ERROR,
Expand Down Expand Up @@ -45,7 +45,13 @@ const kOnCouldNotSerializeErr = Symbol('kOnCouldNotSerializeErr');
const kOnErrorMessage = Symbol('kOnErrorMessage');
const kParentSideStdio = Symbol('kParentSideStdio');

const debug = util.debuglog('worker');
let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('worker');
}
debuglog(...args);
}

class Worker extends EventEmitter {
constructor(filename, options = {}) {
Expand Down
9 changes: 8 additions & 1 deletion lib/internal/worker/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ const { threadId } = internalBinding('worker');
const { Readable, Writable } = require('stream');
const EventEmitter = require('events');
const util = require('util');
const debug = util.debuglog('worker');

let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('worker');
}
debuglog(...args);
}

const kIncrementsPortRef = Symbol('kIncrementsPortRef');
const kName = Symbol('kName');
Expand Down
10 changes: 9 additions & 1 deletion lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ const {
const internalUtil = require('internal/util');
const util = require('util');
const { ERR_INVALID_CALLBACK } = require('internal/errors').codes;
const debug = util.debuglog('timer');

let debuglog;
function debug(...args) {
if (!debuglog) {
debuglog = require('internal/util/debuglog').debuglog('timer');
}
debuglog(...args);
}

const {
destroyHooksExist,
// The needed emit*() functions.
Expand Down
40 changes: 1 addition & 39 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const {
formatWithOptions,
inspect
} = require('internal/util/inspect');
const { debuglog } = require('internal/util/debuglog');
const {
ERR_FALSY_VALUE_REJECTION,
ERR_INVALID_ARG_TYPE,
Expand All @@ -52,45 +53,6 @@ const objectToString = uncurryThis(Object.prototype.toString);

let internalDeepEqual;

const debugs = {};
let debugEnvRegex = /^$/;
if (process.env.NODE_DEBUG) {
let debugEnv = process.env.NODE_DEBUG;
debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&')
.replace(/\*/g, '.*')
.replace(/,/g, '$|^')
.toUpperCase();
debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i');
}

// Emits warning when user sets
// NODE_DEBUG=http or NODE_DEBUG=http2.
function emitWarningIfNeeded(set) {
if ('HTTP' === set || 'HTTP2' === set) {
process.emitWarning('Setting the NODE_DEBUG environment variable ' +
'to \'' + set.toLowerCase() + '\' can expose sensitive ' +
'data (such as passwords, tokens and authentication headers) ' +
'in the resulting log.');
}
}

function debuglog(set) {
set = set.toUpperCase();
if (!debugs[set]) {
if (debugEnvRegex.test(set)) {
const pid = process.pid;
emitWarningIfNeeded(set);
debugs[set] = function debug() {
const msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function debug() {};
}
}
return debugs[set];
}

function isBoolean(arg) {
return typeof arg === 'boolean';
}
Expand Down
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
'lib/internal/url.js',
'lib/internal/util.js',
'lib/internal/util/comparisons.js',
'lib/internal/util/debuglog.js',
'lib/internal/util/inspect.js',
'lib/internal/util/inspector.js',
'lib/internal/util/types.js',
Expand Down

0 comments on commit b05fd4b

Please sign in to comment.