| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 2d3e735 commit 16802c0
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -122,6 +122,16 @@ added: v6.0.0 | |||
| 122 | 122 | ||
| 123 | 123 | Print stack traces for process warnings (including deprecations). | |
| 124 | 124 | ||
| 125 | + ### `--redirect-warnings=file` | ||
| 126 | + <!-- YAML | ||
| 127 | + added: REPLACEME | ||
| 128 | + --> | ||
| 129 | + | ||
| 130 | + Write process warnings to the given file instead of printing to stderr. The | ||
| 131 | + file will be created if it does not exist, and will be appended to if it does. | ||
| 132 | + If an error occurs while attempting to write the warning to the file, the | ||
| 133 | + warning will be written to stderr instead. | ||
| 134 | + | ||
| 125 | 135 | ### `--trace-sync-io` | |
| 126 | 136 | <!-- YAML | |
| 127 | 137 | added: v2.1.0 | |
@@ -383,6 +393,17 @@ Note: Be aware that unless the child environment is explicitly set, this | |||
| 383 | 393 | evironment variable will be inherited by any child processes, and if they use | |
| 384 | 394 | OpenSSL, it may cause them to trust the same CAs as node. | |
| 385 | 395 | ||
| 396 | + ### `NODE_REDIRECT_WARNINGS=file` | ||
| 397 | + <!-- YAML | ||
| 398 | + added: REPLACEME | ||
| 399 | + --> | ||
| 400 | + | ||
| 401 | + When set, process warnings will be emitted to the given file instead of | ||
| 402 | + printing to stderr. The file will be created if it does not exist, and will be | ||
| 403 | + appended to if it does. If an error occurs while attempting to write the | ||
| 404 | + warning to the file, the warning will be written to stderr instead. This is | ||
| 405 | + equivalent to using the `--redirect-warnings=file` command-line flag. | ||
| 406 | + | ||
| 386 | 407 | [emit_warning]: process.html#process_process_emitwarning_warning_name_ctor | |
| 387 | 408 | [Buffer]: buffer.html#buffer_buffer | |
| 388 | 409 | [debugger]: debugger.html | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -112,6 +112,10 @@ Silence all process warnings (including deprecations). | |||
| 112 | 112 | .BR \-\-trace\-warnings | |
| 113 | 113 | Print stack traces for process warnings (including deprecations). | |
| 114 | 114 | ||
| 115 | + .TP | ||
| 116 | + .BR \-\-redirect\-warnings=\fIfile\fR | ||
| 117 | + Write process warnings to the given file instead of printing to stderr. | ||
| 118 | + | ||
| 115 | 119 | .TP | |
| 116 | 120 | .BR \-\-trace\-sync\-io | |
| 117 | 121 | Print a stack trace whenever synchronous I/O is detected after the first turn | |
@@ -255,6 +259,12 @@ containing trusted certificates. | |||
| 255 | 259 | If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's | |
| 256 | 260 | file containing trusted certificates. | |
| 257 | 261 | ||
| 262 | + .TP | ||
| 263 | + .BR NODE_REDIRECT_WARNINGS=\fIfile\fR | ||
| 264 | + Write process warnings to the given file instead of printing to stderr. | ||
| 265 | + (equivalent to using the \-\-redirect\-warnings=\fIfile\fR command-line | ||
| 266 | + argument). | ||
| 267 | + | ||
| 258 | 268 | .SH BUGS | |
| 259 | 269 | Bugs are tracked in GitHub Issues: | |
| 260 | 270 | .ur https://github.com/nodejs/node/issues | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,10 +4,81 @@ const traceWarnings = process.traceProcessWarnings; | |||
| 4 | 4 | const noDeprecation = process.noDeprecation; | |
| 5 | 5 | const traceDeprecation = process.traceDeprecation; | |
| 6 | 6 | const throwDeprecation = process.throwDeprecation; | |
| 7 | + const config = process.binding('config'); | ||
| 7 | 8 | const prefix = `(${process.release.name}:${process.pid}) `; | |
| 8 | 9 | ||
| 9 | 10 | exports.setup = setupProcessWarnings; | |
| 10 | 11 | ||
| 12 | + var fs; | ||
| 13 | + var cachedFd; | ||
| 14 | + var acquiringFd = false; | ||
| 15 | + function nop() {} | ||
| 16 | + | ||
| 17 | + function lazyFs() { | ||
| 18 | + if (!fs) | ||
| 19 | + fs = require('fs'); | ||
| 20 | + return fs; | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + function writeOut(message) { | ||
| 24 | + if (console && typeof console.error === 'function') | ||
| 25 | + return console.error(message); | ||
| 26 | + process._rawDebug(message); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + function onClose(fd) { | ||
| 30 | + return function() { | ||
| 31 | + lazyFs().close(fd, nop); | ||
| 32 | + }; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + function onOpen(cb) { | ||
| 36 | + return function(err, fd) { | ||
| 37 | + acquiringFd = false; | ||
| 38 | + if (fd !== undefined) { | ||
| 39 | + cachedFd = fd; | ||
| 40 | + process.on('exit', onClose(fd)); | ||
| 41 | + } | ||
| 42 | + cb(err, fd); | ||
| 43 | + process.emit('_node_warning_fd_acquired', err, fd); | ||
| 44 | + }; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + function onAcquired(message) { | ||
| 48 | + // make a best effort attempt at writing the message | ||
| 49 | + // to the fd. Errors are ignored at this point. | ||
| 50 | + return function(err, fd) { | ||
| 51 | + if (err) | ||
| 52 | + return writeOut(message); | ||
| 53 | + lazyFs().appendFile(fd, `${message}\n`, nop); | ||
| 54 | + }; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + function acquireFd(cb) { | ||
| 58 | + if (cachedFd === undefined && !acquiringFd) { | ||
| 59 | + acquiringFd = true; | ||
| 60 | + lazyFs().open(config.warningFile, 'a', onOpen(cb)); | ||
| 61 | + } else if (cachedFd !== undefined && !acquiringFd) { | ||
| 62 | + cb(null, cachedFd); | ||
| 63 | + } else { | ||
| 64 | + process.once('_node_warning_fd_acquired', cb); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + function output(message) { | ||
| 69 | + if (typeof config.warningFile === 'string') { | ||
| 70 | + acquireFd(onAcquired(message)); | ||
| 71 | + return; | ||
| 72 | + } | ||
| 73 | + writeOut(message); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + function doEmitWarning(warning) { | ||
| 77 | + return function() { | ||
| 78 | + process.emit('warning', warning); | ||
| 79 | + }; | ||
| 80 | + } | ||
| 81 | + | ||
| 11 | 82 | function setupProcessWarnings() { | |
| 12 | 83 | if (!process.noProcessWarnings && process.env.NODE_NO_WARNINGS !== '1') { | |
| 13 | 84 | process.on('warning', (warning) => { | |
@@ -21,7 +92,7 @@ function setupProcessWarnings() { | |||
| 21 | 92 | var toString = warning.toString; | |
| 22 | 93 | if (typeof toString !== 'function') | |
| 23 | 94 | toString = Error.prototype.toString; | |
| 24 | - console.error(`${prefix}${toString.apply(warning)}`); | ||
| 95 | + output(`${prefix}${toString.apply(warning)}`); | ||
| 25 | 96 | } | |
| 26 | 97 | }); | |
| 27 | 98 | } | |
@@ -44,6 +115,6 @@ function setupProcessWarnings() { | |||
| 44 | 115 | if (throwDeprecation && warning.name === 'DeprecationWarning') | |
| 45 | 116 | throw warning; | |
| 46 | 117 | else | |
| 47 | - process.nextTick(() => process.emit('warning', warning)); | ||
| 118 | + process.nextTick(doEmitWarning(warning)); | ||
| 48 | 119 | }; | |
| 49 | 120 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -199,12 +199,16 @@ bool trace_warnings = false; | |||
| 199 | 199 | // that is used by lib/module.js | |
| 200 | 200 | bool config_preserve_symlinks = false; | |
| 201 | 201 | ||
| 202 | + | ||
| 202 | 203 | // Set in node.cc by ParseArgs when --expose-internals or --expose_internals is | |
| 203 | 204 | // used. | |
| 204 | 205 | // Used in node_config.cc to set a constant on process.binding('config') | |
| 205 | 206 | // that is used by lib/internal/bootstrap_node.js | |
| 206 | 207 | bool config_expose_internals = false; | |
| 207 | 208 | ||
| 209 | + // Set in node.cc by ParseArgs when --redirect-warnings= is used. | ||
| 210 | + const char* config_warning_file; | ||
| 211 | + | ||
| 208 | 212 | // process-relative uptime base, initialized at start-up | |
| 209 | 213 | static double prog_start_time; | |
| 210 | 214 | static bool debugger_running; | |
@@ -3701,6 +3705,8 @@ static void PrintHelp() { | |||
| 3701 | 3705 | "function is used\n" | |
| 3702 | 3706 | " --no-warnings silence all process warnings\n" | |
| 3703 | 3707 | " --trace-warnings show stack traces on process warnings\n" | |
| 3708 | + " --redirect-warnings=path\n" | ||
| 3709 | + " write warnings to path instead of stderr\n" | ||
| 3704 | 3710 | " --trace-sync-io show stack trace when use of sync IO\n" | |
| 3705 | 3711 | " is detected after the first tick\n" | |
| 3706 | 3712 | " --track-heap-objects track heap object allocations for heap " | |
@@ -3765,6 +3771,7 @@ static void PrintHelp() { | |||
| 3765 | 3771 | " prefixed to the module search path\n" | |
| 3766 | 3772 | "NODE_REPL_HISTORY path to the persistent REPL history file\n" | |
| 3767 | 3773 | "OPENSSL_CONF load OpenSSL configuration from file\n" | |
| 3774 | + "NODE_REDIRECT_WARNINGS write warnings to path instead of stderr\n" | ||
| 3768 | 3775 | "\n" | |
| 3769 | 3776 | "Documentation can be found at https://nodejs.org/\n"); | |
| 3770 | 3777 | } | |
@@ -3866,6 +3873,8 @@ static void ParseArgs(int* argc, | |||
| 3866 | 3873 | no_process_warnings = true; | |
| 3867 | 3874 | } else if (strcmp(arg, "--trace-warnings") == 0) { | |
| 3868 | 3875 | trace_warnings = true; | |
| 3876 | + } else if (strncmp(arg, "--redirect-warnings=", 20) == 0) { | ||
| 3877 | + config_warning_file = arg + 20; | ||
| 3869 | 3878 | } else if (strcmp(arg, "--trace-deprecation") == 0) { | |
| 3870 | 3879 | trace_deprecation = true; | |
| 3871 | 3880 | } else if (strcmp(arg, "--trace-sync-io") == 0) { | |
@@ -4401,6 +4410,10 @@ void Init(int* argc, | |||
| 4401 | 4410 | if (openssl_config.empty()) | |
| 4402 | 4411 | SafeGetenv("OPENSSL_CONF", &openssl_config); | |
| 4403 | 4412 | ||
| 4413 | + if (auto redirect_warnings = secure_getenv("NODE_REDIRECT_WARNINGS")) { | ||
| 4414 | + config_warning_file = redirect_warnings; | ||
| 4415 | + } | ||
| 4416 | + | ||
| 4404 | 4417 | // Parse a few arguments which are specific to Node. | |
| 4405 | 4418 | int v8_argc; | |
| 4406 | 4419 | const char** v8_argv; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,6 +12,7 @@ using v8::Context; | |||
| 12 | 12 | using v8::Local; | |
| 13 | 13 | using v8::Object; | |
| 14 | 14 | using v8::ReadOnly; | |
| 15 | + using v8::String; | ||
| 15 | 16 | using v8::Value; | |
| 16 | 17 | ||
| 17 | 18 | // The config binding is used to provide an internal view of compile or runtime | |
@@ -47,6 +48,15 @@ void InitConfig(Local<Object> target, | |||
| 47 | 48 | ||
| 48 | 49 | if (config_expose_internals) | |
| 49 | 50 | READONLY_BOOLEAN_PROPERTY("exposeInternals"); | |
| 51 | + | ||
| 52 | + if (config_warning_file != nullptr) { | ||
| 53 | + Local<String> name = OneByteString(env->isolate(), "warningFile"); | ||
| 54 | + Local<String> value = String::NewFromUtf8(env->isolate(), | ||
| 55 | + config_warning_file, | ||
| 56 | + v8::NewStringType::kNormal) | ||
| 57 | + .ToLocalChecked(); | ||
| 58 | + target->DefineOwnProperty(env->context(), name, value).FromJust(); | ||
| 59 | + } | ||
| 50 | 60 | } // InitConfig | |
| 51 | 61 | ||
| 52 | 62 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -49,6 +49,11 @@ extern bool config_preserve_symlinks; | |||
| 49 | 49 | // that is used by lib/internal/bootstrap_node.js | |
| 50 | 50 | extern bool config_expose_internals; | |
| 51 | 51 | ||
| 52 | + // Set in node.cc by ParseArgs when --redirect-warnings= is used. | ||
| 53 | + // Used to redirect warning output to a file rather than sending | ||
| 54 | + // it to stderr. | ||
| 55 | + extern const char* config_warning_file; | ||
| 56 | + | ||
| 52 | 57 | // Forward declaration | |
| 53 | 58 | class Environment; | |
| 54 | 59 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,25 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + // Tests the NODE_REDIRECT_WARNINGS environment variable by spawning | ||
| 4 | + // a new child node process that emits a warning into a temporary | ||
| 5 | + // warnings file. Once the process completes, the warning file is | ||
| 6 | + // opened and the contents are validated | ||
| 7 | + | ||
| 8 | + const common = require('../common'); | ||
| 9 | + const fs = require('fs'); | ||
| 10 | + const fork = require('child_process').fork; | ||
| 11 | + const path = require('path'); | ||
| 12 | + const assert = require('assert'); | ||
| 13 | + | ||
| 14 | + common.refreshTmpDir(); | ||
| 15 | + | ||
| 16 | + const warnmod = require.resolve(common.fixturesDir + '/warnings.js'); | ||
| 17 | + const warnpath = path.join(common.tmpDir, 'warnings.txt'); | ||
| 18 | + | ||
| 19 | + fork(warnmod, {env: {NODE_REDIRECT_WARNINGS: warnpath}}) | ||
| 20 | + .on('exit', common.mustCall(() => { | ||
| 21 | + fs.readFile(warnpath, 'utf8', common.mustCall((err, data) => { | ||
| 22 | + assert.ifError(err); | ||
| 23 | + assert(/\(node:\d+\) Warning: a bad practice warning/.test(data)); | ||
| 24 | + })); | ||
| 25 | + })); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,25 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + // Tests the --redirect-warnings command line flag by spawning | ||
| 4 | + // a new child node process that emits a warning into a temporary | ||
| 5 | + // warnings file. Once the process completes, the warning file is | ||
| 6 | + // opened and the contents are validated | ||
| 7 | + | ||
| 8 | + const common = require('../common'); | ||
| 9 | + const fs = require('fs'); | ||
| 10 | + const fork = require('child_process').fork; | ||
| 11 | + const path = require('path'); | ||
| 12 | + const assert = require('assert'); | ||
| 13 | + | ||
| 14 | + common.refreshTmpDir(); | ||
| 15 | + | ||
| 16 | + const warnmod = require.resolve(common.fixturesDir + '/warnings.js'); | ||
| 17 | + const warnpath = path.join(common.tmpDir, 'warnings.txt'); | ||
| 18 | + | ||
| 19 | + fork(warnmod, {execArgv: [`--redirect-warnings=${warnpath}`]}) | ||
| 20 | + .on('exit', common.mustCall(() => { | ||
| 21 | + fs.readFile(warnpath, 'utf8', common.mustCall((err, data) => { | ||
| 22 | + assert.ifError(err); | ||
| 23 | + assert(/\(node:\d+\) Warning: a bad practice warning/.test(data)); | ||
| 24 | + })); | ||
| 25 | + })); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments