Skip to content

Commit 5ca5864

Browse files
addaleaxMylesBorins
authored andcommitted
cli: add --trace-uncaught flag
Add a flag that makes Node.js print the stack trace at the time of *throwing* uncaught exceptions, rather than at the creation of the `Error` object, if there is any. This is disabled by default because it affects GC behavior. PR-URL: #30025 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
1 parent 39070bb commit 5ca5864

17 files changed

+111
-0
lines changed

doc/api/cli.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,18 @@ added: v12.2.0
748748
Prints TLS packet trace information to `stderr`. This can be used to debug TLS
749749
connection problems.
750750

751+
### `--trace-uncaught`
752+
<!-- YAML
753+
added: REPLACEME
754+
-->
755+
756+
Print stack traces for uncaught exceptions; usually, the stack trace associated
757+
with the creation of an `Error` is printed, whereas this makes Node.js also
758+
print the stack trace associated with throwing the value (which does not need
759+
to be an `Error` instance).
760+
761+
Enabling this option may affect garbage collection behavior negatively.
762+
751763
### `--trace-warnings`
752764
<!-- YAML
753765
added: v6.0.0
@@ -1045,6 +1057,7 @@ Node.js options that are allowed are:
10451057
* `--trace-events-enabled`
10461058
* `--trace-sync-io`
10471059
* `--trace-tls`
1060+
* `--trace-uncaught`
10481061
* `--trace-warnings`
10491062
* `--track-heap-objects`
10501063
* `--unhandled-rejections`

doc/node.1

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,18 @@ Print a stack trace whenever synchronous I/O is detected after the first turn of
337337
.It Fl -trace-tls
338338
Prints TLS packet trace information to stderr.
339339
.
340+
.It Fl -trace-uncaught
341+
Print stack traces for uncaught exceptions; usually, the stack trace associated
342+
with the creation of an
343+
.Sy Error
344+
is printed, whereas this makes Node.js also
345+
print the stack trace associated with throwing the value (which does not need
346+
to be an
347+
.Sy Error
348+
instance).
349+
.Pp
350+
Enabling this option may affect garbage collection behavior negatively.
351+
.
340352
.It Fl -trace-warnings
341353
Print stack traces for process warnings (including deprecations).
342354
.

src/node.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ int Environment::InitializeInspector(
265265
void Environment::InitializeDiagnostics() {
266266
isolate_->GetHeapProfiler()->AddBuildEmbedderGraphCallback(
267267
Environment::BuildEmbedderGraph, this);
268+
if (options_->trace_uncaught)
269+
isolate_->SetCaptureStackTraceForUncaughtExceptions(true);
268270

269271
#if defined HAVE_DTRACE || defined HAVE_ETW
270272
InitDTrace(this);

src/node_errors.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,19 @@ static void ReportFatalException(Environment* env,
380380
"%s\n%s: %s\n", *arrow_string, *name_string, *message_string);
381381
}
382382
}
383+
384+
if (!env->options()->trace_uncaught) {
385+
PrintErrorString("(Use `node --trace-uncaught ...` to show "
386+
"where the exception was thrown)\n");
387+
}
388+
}
389+
390+
if (env->options()->trace_uncaught) {
391+
Local<StackTrace> trace = message->GetStackTrace();
392+
if (!trace.IsEmpty()) {
393+
PrintErrorString("Thrown at:\n");
394+
PrintStackTrace(env->isolate(), trace);
395+
}
383396
}
384397

385398
fflush(stderr);

src/node_options.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
476476
"prints TLS packet trace information to stderr",
477477
&EnvironmentOptions::trace_tls,
478478
kAllowedInEnvironment);
479+
AddOption("--trace-uncaught",
480+
"show stack traces for the `throw` behind uncaught exceptions",
481+
&EnvironmentOptions::trace_uncaught,
482+
kAllowedInEnvironment);
479483
AddOption("--trace-warnings",
480484
"show stack traces on process warnings",
481485
&EnvironmentOptions::trace_warnings,

src/node_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class EnvironmentOptions : public Options {
140140
bool trace_deprecation = false;
141141
bool trace_sync_io = false;
142142
bool trace_tls = false;
143+
bool trace_uncaught = false;
143144
bool trace_warnings = false;
144145
std::string unhandled_rejections;
145146
std::string userland_loader;

test/message/eval_messages.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ ReferenceError: y is not defined
5555
var ______________________________________________; throw 10
5656
^
5757
10
58+
(Use `node --trace-uncaught ...` to show where the exception was thrown)
5859

5960
[eval]:1
6061
var ______________________________________________; throw 10
6162
^
6263
10
64+
(Use `node --trace-uncaught ...` to show where the exception was thrown)
6365
done

test/message/stdin_messages.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ ReferenceError: y is not defined
6767
var ______________________________________________; throw 10
6868
^
6969
10
70+
(Use `node --trace-uncaught ...` to show where the exception was thrown)
7071

7172
[stdin]:1
7273
var ______________________________________________; throw 10
7374
^
7475
10
76+
(Use `node --trace-uncaught ...` to show where the exception was thrown)
7577
done

test/message/throw_error_with_getter_throw.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
throw { // eslint-disable-line no-throw-literal
44
^
55
[object Object]
6+
(Use `node --trace-uncaught ...` to show where the exception was thrown)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Flags: --trace-uncaught
2+
'use strict';
3+
require('../common');
4+
throw { // eslint-disable-line no-throw-literal
5+
get stack() {
6+
throw new Error('weird throw but ok');
7+
},
8+
get name() {
9+
throw new Error('weird throw but ok');
10+
},
11+
};

0 commit comments

Comments
 (0)