| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5e1f32f commit 03e89b3
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -121,6 +121,16 @@ added: v6.0.0 | |||
| 121 | 121 | ||
| 122 | 122 | Print stack traces for process warnings (including deprecations). | |
| 123 | 123 | ||
| 124 | + ### `--redirect-warnings=file` | ||
| 125 | + <!-- YAML | ||
| 126 | + added: REPLACEME | ||
| 127 | + --> | ||
| 128 | + | ||
| 129 | + Write process warnings to the given file instead of printing to stderr. The | ||
| 130 | + file will be created if it does not exist, and will be appended to if it does. | ||
| 131 | + If an error occurs while attempting to write the warning to the file, the | ||
| 132 | + warning will be written to stderr instead. | ||
| 133 | + | ||
| 124 | 134 | ### `--trace-sync-io` | |
| 125 | 135 | <!-- YAML | |
| 126 | 136 | added: v2.1.0 | |
@@ -395,6 +405,17 @@ Note: Be aware that unless the child environment is explicitly set, this | |||
| 395 | 405 | evironment variable will be inherited by any child processes, and if they use | |
| 396 | 406 | OpenSSL, it may cause them to trust the same CAs as node. | |
| 397 | 407 | ||
| 408 | + ### `NODE_REDIRECT_WARNINGS=file` | ||
| 409 | + <!-- YAML | ||
| 410 | + added: REPLACEME | ||
| 411 | + --> | ||
| 412 | + | ||
| 413 | + When set, process warnings will be emitted to the given file instead of | ||
| 414 | + printing to stderr. The file will be created if it does not exist, and will be | ||
| 415 | + appended to if it does. If an error occurs while attempting to write the | ||
| 416 | + warning to the file, the warning will be written to stderr instead. This is | ||
| 417 | + equivalent to using the `--redirect-warnings=file` command-line flag. | ||
| 418 | + | ||
| 398 | 419 | [emit_warning]: process.html#process_process_emitwarning_warning_name_ctor | |
| 399 | 420 | [Buffer]: buffer.html#buffer_buffer | |
| 400 | 421 | [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 | |
@@ -262,6 +266,12 @@ containing trusted certificates. | |||
| 262 | 266 | If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's | |
| 263 | 267 | file containing trusted certificates. | |
| 264 | 268 | ||
| 269 | + .TP | ||
| 270 | + .BR NODE_REDIRECT_WARNINGS=\fIfile\fR | ||
| 271 | + Write process warnings to the given file instead of printing to stderr. | ||
| 272 | + (equivalent to using the \-\-redirect\-warnings=\fIfile\fR command-line | ||
| 273 | + argument). | ||
| 274 | + | ||
| 265 | 275 | .SH BUGS | |
| 266 | 276 | Bugs are tracked in GitHub Issues: | |
| 267 | 277 | .ur https://github.com/nodejs/node/issues | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,9 +1,80 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | + const config = process.binding('config'); | ||
| 3 | 4 | const prefix = `(${process.release.name}:${process.pid}) `; | |
| 4 | 5 | ||
| 5 | 6 | exports.setup = setupProcessWarnings; | |
| 6 | 7 | ||
| 8 | + var fs; | ||
| 9 | + var cachedFd; | ||
| 10 | + var acquiringFd = false; | ||
| 11 | + function nop() {} | ||
| 12 | + | ||
| 13 | + function lazyFs() { | ||
| 14 | + if (!fs) | ||
| 15 | + fs = require('fs'); | ||
| 16 | + return fs; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + function writeOut(message) { | ||
| 20 | + if (console && typeof console.error === 'function') | ||
| 21 | + return console.error(message); | ||
| 22 | + process._rawDebug(message); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + function onClose(fd) { | ||
| 26 | + return function() { | ||
| 27 | + lazyFs().close(fd, nop); | ||
| 28 | + }; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + function onOpen(cb) { | ||
| 32 | + return function(err, fd) { | ||
| 33 | + acquiringFd = false; | ||
| 34 | + if (fd !== undefined) { | ||
| 35 | + cachedFd = fd; | ||
| 36 | + process.on('exit', onClose(fd)); | ||
| 37 | + } | ||
| 38 | + cb(err, fd); | ||
| 39 | + process.emit('_node_warning_fd_acquired', err, fd); | ||
| 40 | + }; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + function onAcquired(message) { | ||
| 44 | + // make a best effort attempt at writing the message | ||
| 45 | + // to the fd. Errors are ignored at this point. | ||
| 46 | + return function(err, fd) { | ||
| 47 | + if (err) | ||
| 48 | + return writeOut(message); | ||
| 49 | + lazyFs().appendFile(fd, `${message}\n`, nop); | ||
| 50 | + }; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + function acquireFd(cb) { | ||
| 54 | + if (cachedFd === undefined && !acquiringFd) { | ||
| 55 | + acquiringFd = true; | ||
| 56 | + lazyFs().open(config.warningFile, 'a', onOpen(cb)); | ||
| 57 | + } else if (cachedFd !== undefined && !acquiringFd) { | ||
| 58 | + cb(null, cachedFd); | ||
| 59 | + } else { | ||
| 60 | + process.once('_node_warning_fd_acquired', cb); | ||
| 61 | + } | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + function output(message) { | ||
| 65 | + if (typeof config.warningFile === 'string') { | ||
| 66 | + acquireFd(onAcquired(message)); | ||
| 67 | + return; | ||
| 68 | + } | ||
| 69 | + writeOut(message); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + function doEmitWarning(warning) { | ||
| 73 | + return function() { | ||
| 74 | + process.emit('warning', warning); | ||
| 75 | + }; | ||
| 76 | + } | ||
| 77 | + | ||
| 7 | 78 | function setupProcessWarnings() { | |
| 8 | 79 | if (!process.noProcessWarnings && process.env.NODE_NO_WARNINGS !== '1') { | |
| 9 | 80 | process.on('warning', (warning) => { | |
@@ -14,19 +85,18 @@ function setupProcessWarnings() { | |||
| 14 | 85 | (isDeprecation && process.traceDeprecation); | |
| 15 | 86 | if (trace && warning.stack) { | |
| 16 | 87 | if (warning.code) { | |
| 17 | - console.error(`${prefix}[${warning.code}] ${warning.stack}`); | ||
| 88 | + output(`${prefix}[${warning.code}] ${warning.stack}`); | ||
| 18 | 89 | } else { | |
| 19 | - console.error(`${prefix}${warning.stack}`); | ||
| 90 | + output(`${prefix}${warning.stack}`); | ||
| 20 | 91 | } | |
| 21 | 92 | } else { | |
| 22 | 93 | const toString = | |
| 23 | 94 | typeof warning.toString === 'function' ? | |
| 24 | 95 | warning.toString : Error.prototype.toString; | |
| 25 | 96 | if (warning.code) { | |
| 26 | - console.error( | ||
| 27 | - `${prefix}[${warning.code}] ${toString.apply(warning)}`); | ||
| 97 | + output(`${prefix}[${warning.code}] ${toString.apply(warning)}`); | ||
| 28 | 98 | } else { | |
| 29 | - console.error(`${prefix}${toString.apply(warning)}`); | ||
| 99 | + output(`${prefix}${toString.apply(warning)}`); | ||
| 30 | 100 | } | |
| 31 | 101 | } | |
| 32 | 102 | }); | |
@@ -63,6 +133,6 @@ function setupProcessWarnings() { | |||
| 63 | 133 | if (process.throwDeprecation) | |
| 64 | 134 | throw warning; | |
| 65 | 135 | } | |
| 66 | - process.nextTick(() => process.emit('warning', warning)); | ||
| 136 | + process.nextTick(doEmitWarning(warning)); | ||
| 67 | 137 | }; | |
| 68 | 138 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -188,6 +188,9 @@ bool trace_warnings = false; | |||
| 188 | 188 | // that is used by lib/module.js | |
| 189 | 189 | bool config_preserve_symlinks = false; | |
| 190 | 190 | ||
| 191 | + // Set in node.cc by ParseArgs when --redirect-warnings= is used. | ||
| 192 | + const char* config_warning_file; | ||
| 193 | + | ||
| 191 | 194 | bool v8_initialized = false; | |
| 192 | 195 | ||
| 193 | 196 | // process-relative uptime base, initialized at start-up | |
@@ -3499,6 +3502,9 @@ static void PrintHelp() { | |||
| 3499 | 3502 | " --throw-deprecation throw an exception on deprecations\n" | |
| 3500 | 3503 | " --no-warnings silence all process warnings\n" | |
| 3501 | 3504 | " --trace-warnings show stack traces on process warnings\n" | |
| 3505 | + " --redirect-warnings=path\n" | ||
| 3506 | + " write warnings to path instead of\n" | ||
| 3507 | + " stderr\n" | ||
| 3502 | 3508 | " --trace-sync-io show stack trace when use of sync IO\n" | |
| 3503 | 3509 | " is detected after the first tick\n" | |
| 3504 | 3510 | " --trace-events-enabled track trace events\n" | |
@@ -3564,6 +3570,8 @@ static void PrintHelp() { | |||
| 3564 | 3570 | " prefixed to the module search path\n" | |
| 3565 | 3571 | "NODE_REPL_HISTORY path to the persistent REPL history\n" | |
| 3566 | 3572 | " file\n" | |
| 3573 | + "NODE_REDIRECT_WARNINGS write warnings to path instead of\n" | ||
| 3574 | + " stderr\n" | ||
| 3567 | 3575 | "Documentation can be found at https://nodejs.org/\n"); | |
| 3568 | 3576 | } | |
| 3569 | 3577 | ||
@@ -3664,6 +3672,8 @@ static void ParseArgs(int* argc, | |||
| 3664 | 3672 | no_process_warnings = true; | |
| 3665 | 3673 | } else if (strcmp(arg, "--trace-warnings") == 0) { | |
| 3666 | 3674 | trace_warnings = true; | |
| 3675 | + } else if (strncmp(arg, "--redirect-warnings=", 20) == 0) { | ||
| 3676 | + config_warning_file = arg + 20; | ||
| 3667 | 3677 | } else if (strcmp(arg, "--trace-deprecation") == 0) { | |
| 3668 | 3678 | trace_deprecation = true; | |
| 3669 | 3679 | } else if (strcmp(arg, "--trace-sync-io") == 0) { | |
@@ -4206,6 +4216,10 @@ void Init(int* argc, | |||
| 4206 | 4216 | config_preserve_symlinks = (*preserve_symlinks == '1'); | |
| 4207 | 4217 | } | |
| 4208 | 4218 | ||
| 4219 | + if (auto redirect_warnings = secure_getenv("NODE_REDIRECT_WARNINGS")) { | ||
| 4220 | + config_warning_file = redirect_warnings; | ||
| 4221 | + } | ||
| 4222 | + | ||
| 4209 | 4223 | // Parse a few arguments which are specific to Node. | |
| 4210 | 4224 | int v8_argc; | |
| 4211 | 4225 | 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 | |
@@ -44,6 +45,15 @@ void InitConfig(Local<Object> target, | |||
| 44 | 45 | ||
| 45 | 46 | if (config_preserve_symlinks) | |
| 46 | 47 | READONLY_BOOLEAN_PROPERTY("preserveSymlinks"); | |
| 48 | + | ||
| 49 | + if (config_warning_file != nullptr) { | ||
| 50 | + Local<String> name = OneByteString(env->isolate(), "warningFile"); | ||
| 51 | + Local<String> value = String::NewFromUtf8(env->isolate(), | ||
| 52 | + config_warning_file, | ||
| 53 | + v8::NewStringType::kNormal) | ||
| 54 | + .ToLocalChecked(); | ||
| 55 | + target->DefineOwnProperty(env->context(), name, value).FromJust(); | ||
| 56 | + } | ||
| 47 | 57 | } // InitConfig | |
| 48 | 58 | ||
| 49 | 59 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -42,6 +42,11 @@ extern const char* openssl_config; | |||
| 42 | 42 | // that is used by lib/module.js | |
| 43 | 43 | extern bool config_preserve_symlinks; | |
| 44 | 44 | ||
| 45 | + // Set in node.cc by ParseArgs when --redirect-warnings= is used. | ||
| 46 | + // Used to redirect warning output to a file rather than sending | ||
| 47 | + // it to stderr. | ||
| 48 | + extern const char* config_warning_file; | ||
| 49 | + | ||
| 45 | 50 | // Tells whether it is safe to call v8::Isolate::GetCurrent(). | |
| 46 | 51 | extern bool v8_initialized; | |
| 47 | 52 | ||
| 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