Skip to content

Commit e6a79f8

Browse files
joyeecheungtpoisseau
authored andcommitted
src: parse --stack-trace-limit and use it in --trace-* flags
Previously, --trace-exit and --trace-sync-io doesn't take care of --stack-trace-limit and always print a stack trace with maximum size of 10. This patch parses --stack-trace-limit during initialization and use the value in --trace-* flags. PR-URL: nodejs#55121 Fixes: nodejs#55100 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]>
1 parent 0345c2b commit e6a79f8

File tree

8 files changed

+88
-9
lines changed

8 files changed

+88
-9
lines changed

src/env-inl.h

+4
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,10 @@ inline double Environment::get_default_trigger_async_id() {
433433
return default_trigger_async_id;
434434
}
435435

436+
inline int64_t Environment::stack_trace_limit() const {
437+
return isolate_data_->options()->stack_trace_limit;
438+
}
439+
436440
inline std::shared_ptr<EnvironmentOptions> Environment::options() {
437441
return options_;
438442
}

src/env.cc

+10-6
Original file line numberDiff line numberDiff line change
@@ -1241,9 +1241,11 @@ void Environment::PrintSyncTrace() const {
12411241

12421242
fprintf(
12431243
stderr, "(node:%d) WARNING: Detected use of sync API\n", uv_os_getpid());
1244-
PrintStackTrace(isolate(),
1245-
StackTrace::CurrentStackTrace(
1246-
isolate(), stack_trace_limit(), StackTrace::kDetailed));
1244+
PrintStackTrace(
1245+
isolate(),
1246+
StackTrace::CurrentStackTrace(isolate(),
1247+
static_cast<int>(stack_trace_limit()),
1248+
StackTrace::kDetailed));
12471249
}
12481250

12491251
MaybeLocal<Value> Environment::RunSnapshotSerializeCallback() const {
@@ -1845,9 +1847,11 @@ void Environment::Exit(ExitCode exit_code) {
18451847
fprintf(stderr,
18461848
"WARNING: Exited the environment with code %d\n",
18471849
static_cast<int>(exit_code));
1848-
PrintStackTrace(isolate(),
1849-
StackTrace::CurrentStackTrace(
1850-
isolate(), stack_trace_limit(), StackTrace::kDetailed));
1850+
PrintStackTrace(
1851+
isolate(),
1852+
StackTrace::CurrentStackTrace(isolate(),
1853+
static_cast<int>(stack_trace_limit()),
1854+
StackTrace::kDetailed));
18511855
}
18521856
process_exit_handler_(this, exit_code);
18531857
}

src/env.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ class Environment final : public MemoryRetainer {
977977
inline std::shared_ptr<EnvironmentOptions> options();
978978
inline std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port();
979979

980-
inline int32_t stack_trace_limit() const { return 10; }
980+
inline int64_t stack_trace_limit() const;
981981

982982
#if HAVE_INSPECTOR
983983
void set_coverage_connection(

src/node_options-inl.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,14 @@ void OptionsParser<Options>::Parse(
447447
case kBoolean:
448448
*Lookup<bool>(info.field, options) = !is_negation;
449449
break;
450-
case kInteger:
450+
case kInteger: {
451+
// Special case to pass --stack-trace-limit down to V8.
452+
if (name == "--stack-trace-limit") {
453+
v8_args->push_back(arg);
454+
}
451455
*Lookup<int64_t>(info.field, options) = std::atoll(value.c_str());
452456
break;
457+
}
453458
case kUInteger:
454459
*Lookup<uint64_t>(info.field, options) =
455460
std::strtoull(value.c_str(), nullptr, 10);

src/node_options.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,10 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
904904
"--perf-basic-prof-only-functions", "", V8Option{}, kAllowedInEnvvar);
905905
AddOption("--perf-prof", "", V8Option{}, kAllowedInEnvvar);
906906
AddOption("--perf-prof-unwinding-info", "", V8Option{}, kAllowedInEnvvar);
907-
AddOption("--stack-trace-limit", "", V8Option{}, kAllowedInEnvvar);
907+
AddOption("--stack-trace-limit",
908+
"",
909+
&PerIsolateOptions::stack_trace_limit,
910+
kAllowedInEnvvar);
908911
AddOption("--disallow-code-generation-from-strings",
909912
"disallow eval and friends",
910913
V8Option{},
@@ -1291,6 +1294,11 @@ void GetCLIOptionsValues(const FunctionCallbackInfo<Value>& args) {
12911294
if (item.first == "--abort-on-uncaught-exception") {
12921295
value = Boolean::New(isolate,
12931296
s.original_per_env->abort_on_uncaught_exception);
1297+
} else if (item.first == "--stack-trace-limit") {
1298+
value =
1299+
Number::New(isolate,
1300+
static_cast<double>(
1301+
*_ppop_instance.Lookup<int64_t>(field, opts)));
12941302
} else {
12951303
value = undefined_value;
12961304
}

src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ class PerIsolateOptions : public Options {
271271
bool report_uncaught_exception = false;
272272
bool report_on_signal = false;
273273
bool experimental_shadow_realm = false;
274+
int64_t stack_trace_limit = 10;
274275
std::string report_signal = "SIGUSR2";
275276
bool build_snapshot = false;
276277
std::string build_snapshot_config;

test/fixtures/deep-exit.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
// This is meant to be run with --trace-exit.
4+
5+
const depth = parseInt(process.env.STACK_DEPTH) || 30;
6+
let counter = 1;
7+
function recurse() {
8+
if (counter++ < depth) {
9+
recurse();
10+
} else {
11+
process.exit(0);
12+
}
13+
}
14+
15+
recurse();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
// This tests that --stack-trace-limit can be used to tweak the stack trace size of --trace-exit.
4+
require('../common');
5+
const fixture = require('../common/fixtures');
6+
const { spawnSyncAndAssert } = require('../common/child_process');
7+
const assert = require('assert');
8+
9+
// When the stack trace limit is bigger than the stack trace size, it should output them all.
10+
spawnSyncAndAssert(
11+
process.execPath,
12+
['--trace-exit', '--stack-trace-limit=50', fixture.path('deep-exit.js')],
13+
{
14+
env: {
15+
...process.env,
16+
STACK_DEPTH: 30
17+
}
18+
},
19+
{
20+
stderr(output) {
21+
const matches = [...output.matchAll(/at recurse/g)];
22+
assert.strictEqual(matches.length, 30);
23+
}
24+
});
25+
26+
// When the stack trace limit is smaller than the stack trace size, it should truncate the stack size.
27+
spawnSyncAndAssert(
28+
process.execPath,
29+
['--trace-exit', '--stack-trace-limit=30', fixture.path('deep-exit.js')],
30+
{
31+
env: {
32+
...process.env,
33+
STACK_DEPTH: 30
34+
}
35+
},
36+
{
37+
stderr(output) {
38+
const matches = [...output.matchAll(/at recurse/g)];
39+
// The top frame is process.exit(), so one frame from recurse() is truncated.
40+
assert.strictEqual(matches.length, 29);
41+
}
42+
});

0 commit comments

Comments
 (0)