lib: explicitly initialize debuglog during bootstrap

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: https://github.com/nodejs/node/pull/26468
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
Joyee Cheung 2019-03-06 12:54:12 +01:00
parent 687f30467b
commit b05fd4baa8
No known key found for this signature in database
GPG Key ID: 92B78A53C8303B8D
10 changed files with 108 additions and 46 deletions

View File

@ -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');

View File

@ -18,6 +18,8 @@ function prepareMainThreadExecution() {
setupCoverageHooks(process.env.NODE_V8_COVERAGE);
}
setupDebugEnv();
// Only main thread receives signals.
setupSignalHandlers();
@ -91,6 +93,10 @@ function initializeReport() {
});
}
function setupDebugEnv() {
require('internal/util/debuglog').initializeDebugEnv(process.env.NODE_DEBUG);
}
function setupSignalHandlers() {
const {
createSignalHandlers
@ -286,6 +292,7 @@ function loadPreloadModules() {
module.exports = {
setupCoverageHooks,
setupWarningHandler,
setupDebugEnv,
prepareMainThreadExecution,
initializeDeprecations,
initializeESMLoader,

View File

@ -6,6 +6,7 @@
const {
setupCoverageHooks,
setupWarningHandler,
setupDebugEnv,
initializeDeprecations,
initializeESMLoader,
initializeFrozenIntrinsics,
@ -39,6 +40,9 @@ const {
} = require('internal/process/execution');
const publicWorker = require('worker_threads');
setupDebugEnv();
const debug = require('util').debuglog('worker');
setupWarningHandler();

View File

@ -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');

View File

@ -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
};

View File

@ -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,
@ -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 = {}) {

View File

@ -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');

View File

@ -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.

View File

@ -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,
@ -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';
}

View File

@ -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',