Skip to content

Commit b229083

Browse files
joyeecheungtargos
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: #55121 Fixes: #55100 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent a57c8ba commit b229083

8 files changed

+88
-9
lines changed

src/env-inl.h

+4
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ inline double Environment::get_default_trigger_async_id() {
458458
return default_trigger_async_id;
459459
}
460460

461+
inline int64_t Environment::stack_trace_limit() const {
462+
return isolate_data_->options()->stack_trace_limit;
463+
}
464+
461465
inline std::shared_ptr<EnvironmentOptions> Environment::options() {
462466
return options_;
463467
}

src/env.cc

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

12531253
fprintf(
12541254
stderr, "(node:%d) WARNING: Detected use of sync API\n", uv_os_getpid());
1255-
PrintStackTrace(isolate(),
1256-
StackTrace::CurrentStackTrace(
1257-
isolate(), stack_trace_limit(), StackTrace::kDetailed));
1255+
PrintStackTrace(
1256+
isolate(),
1257+
StackTrace::CurrentStackTrace(isolate(),
1258+
static_cast<int>(stack_trace_limit()),
1259+
StackTrace::kDetailed));
12581260
}
12591261

12601262
MaybeLocal<Value> Environment::RunSnapshotSerializeCallback() const {
@@ -1856,9 +1858,11 @@ void Environment::Exit(ExitCode exit_code) {
18561858
fprintf(stderr,
18571859
"WARNING: Exited the environment with code %d\n",
18581860
static_cast<int>(exit_code));
1859-
PrintStackTrace(isolate(),
1860-
StackTrace::CurrentStackTrace(
1861-
isolate(), stack_trace_limit(), StackTrace::kDetailed));
1861+
PrintStackTrace(
1862+
isolate(),
1863+
StackTrace::CurrentStackTrace(isolate(),
1864+
static_cast<int>(stack_trace_limit()),
1865+
StackTrace::kDetailed));
18621866
}
18631867
process_exit_handler_(this, exit_code);
18641868
}

src/env.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ class Environment final : public MemoryRetainer {
981981
inline std::shared_ptr<EnvironmentOptions> options();
982982
inline std::shared_ptr<ExclusiveAccess<HostPort>> inspector_host_port();
983983

984-
inline int32_t stack_trace_limit() const { return 10; }
984+
inline int64_t stack_trace_limit() const;
985985

986986
#if HAVE_INSPECTOR
987987
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
@@ -921,7 +921,10 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
921921
"--perf-basic-prof-only-functions", "", V8Option{}, kAllowedInEnvvar);
922922
AddOption("--perf-prof", "", V8Option{}, kAllowedInEnvvar);
923923
AddOption("--perf-prof-unwinding-info", "", V8Option{}, kAllowedInEnvvar);
924-
AddOption("--stack-trace-limit", "", V8Option{}, kAllowedInEnvvar);
924+
AddOption("--stack-trace-limit",
925+
"",
926+
&PerIsolateOptions::stack_trace_limit,
927+
kAllowedInEnvvar);
925928
AddOption("--disallow-code-generation-from-strings",
926929
"disallow eval and friends",
927930
V8Option{},
@@ -1313,6 +1316,11 @@ void GetCLIOptionsValues(const FunctionCallbackInfo<Value>& args) {
13131316
if (item.first == "--abort-on-uncaught-exception") {
13141317
value = Boolean::New(isolate,
13151318
s.original_per_env->abort_on_uncaught_exception);
1319+
} else if (item.first == "--stack-trace-limit") {
1320+
value =
1321+
Number::New(isolate,
1322+
static_cast<double>(
1323+
*_ppop_instance.Lookup<int64_t>(field, opts)));
13161324
} else {
13171325
value = undefined_value;
13181326
}

src/node_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ class PerIsolateOptions : public Options {
273273
bool report_uncaught_exception = false;
274274
bool report_on_signal = false;
275275
bool experimental_shadow_realm = false;
276+
int64_t stack_trace_limit = 10;
276277
std::string report_signal = "SIGUSR2";
277278
bool build_snapshot = false;
278279
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)