| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 1bcbc70 commit 8dc4e4e
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -796,6 +796,14 @@ added: v7.7.0 | |||
| 796 | 796 | ||
| 797 | 797 | Enables the collection of trace event tracing information. | |
| 798 | 798 | ||
| 799 | + ### `--trace-exit` | ||
| 800 | + <!-- YAML | ||
| 801 | + added: REPLACEME | ||
| 802 | + --> | ||
| 803 | + | ||
| 804 | + Prints a stack trace whenever an environment is exited proactively, | ||
| 805 | + i.e. invoking `process.exit()`. | ||
| 806 | + | ||
| 799 | 807 | ### `--trace-sync-io` | |
| 800 | 808 | <!-- YAML | |
| 801 | 809 | added: v2.1.0 | |
@@ -1139,6 +1147,7 @@ Node.js options that are allowed are: | |||
| 1139 | 1147 | * `--trace-event-categories` | |
| 1140 | 1148 | * `--trace-event-file-pattern` | |
| 1141 | 1149 | * `--trace-events-enabled` | |
| 1150 | + * `--trace-exit` | ||
| 1142 | 1151 | * `--trace-sync-io` | |
| 1143 | 1152 | * `--trace-tls` | |
| 1144 | 1153 | * `--trace-uncaught` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -359,6 +359,10 @@ and | |||
| 359 | 359 | .It Fl -trace-events-enabled | |
| 360 | 360 | Enable the collection of trace event tracing information. | |
| 361 | 361 | . | |
| 362 | + .It Fl -trace-exit | ||
| 363 | + Prints a stack trace whenever an environment is exited proactively, | ||
| 364 | + i.e. invoking `process.exit()`. | ||
| 365 | + . | ||
| 362 | 366 | .It Fl -trace-sync-io | |
| 363 | 367 | Print a stack trace whenever synchronous I/O is detected after the first turn of the event loop. | |
| 364 | 368 | . | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -931,6 +931,21 @@ void AsyncHooks::grow_async_ids_stack() { | |||
| 931 | 931 | uv_key_t Environment::thread_local_env = {}; | |
| 932 | 932 | ||
| 933 | 933 | void Environment::Exit(int exit_code) { | |
| 934 | + if (options()->trace_exit) { | ||
| 935 | + HandleScope handle_scope(isolate()); | ||
| 936 | + | ||
| 937 | + if (is_main_thread()) { | ||
| 938 | + fprintf(stderr, "(node:%d) ", uv_os_getpid()); | ||
| 939 | + } else { | ||
| 940 | + fprintf(stderr, "(node:%d, thread:%llu) ", uv_os_getpid(), thread_id()); | ||
| 941 | + } | ||
| 942 | + | ||
| 943 | + fprintf( | ||
| 944 | + stderr, "WARNING: Exited the environment with code %d\n", exit_code); | ||
| 945 | + PrintStackTrace( | ||
| 946 | + isolate(), | ||
| 947 | + StackTrace::CurrentStackTrace(isolate(), 10, StackTrace::kDetailed)); | ||
| 948 | + } | ||
| 934 | 949 | if (is_main_thread()) { | |
| 935 | 950 | stop_sub_worker_contexts(); | |
| 936 | 951 | DisposePlatform(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -515,6 +515,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 515 | 515 | "show stack traces on deprecations", | |
| 516 | 516 | &EnvironmentOptions::trace_deprecation, | |
| 517 | 517 | kAllowedInEnvironment); | |
| 518 | + AddOption("--trace-exit", | ||
| 519 | + "show stack trace when an environment exits", | ||
| 520 | + &EnvironmentOptions::trace_exit, | ||
| 521 | + kAllowedInEnvironment); | ||
| 518 | 522 | AddOption("--trace-sync-io", | |
| 519 | 523 | "show stack trace when use of sync IO is detected after the " | |
| 520 | 524 | "first tick", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -142,6 +142,7 @@ class EnvironmentOptions : public Options { | |||
| 142 | 142 | bool test_udp_no_try_send = false; | |
| 143 | 143 | bool throw_deprecation = false; | |
| 144 | 144 | bool trace_deprecation = false; | |
| 145 | + bool trace_exit = false; | ||
| 145 | 146 | bool trace_sync_io = false; | |
| 146 | 147 | bool trace_tls = false; | |
| 147 | 148 | bool trace_uncaught = false; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,59 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + const assert = require('assert'); | ||
| 4 | + const { promisify } = require('util'); | ||
| 5 | + const execFile = promisify(require('child_process').execFile); | ||
| 6 | + const { Worker, isMainThread, workerData } = require('worker_threads'); | ||
| 7 | + | ||
| 8 | + const variant = process.argv[process.argv.length - 1]; | ||
| 9 | + switch (true) { | ||
| 10 | + case variant === 'main-thread': { | ||
| 11 | + return; | ||
| 12 | + } | ||
| 13 | + case variant === 'main-thread-exit': { | ||
| 14 | + return process.exit(0); | ||
| 15 | + } | ||
| 16 | + case variant.startsWith('worker-thread'): { | ||
| 17 | + const worker = new Worker(__filename, { workerData: variant }); | ||
| 18 | + worker.on('error', common.mustNotCall()); | ||
| 19 | + worker.on('exit', common.mustCall((code) => { | ||
| 20 | + assert.strictEqual(code, 0); | ||
| 21 | + })); | ||
| 22 | + return; | ||
| 23 | + } | ||
| 24 | + case !isMainThread: { | ||
| 25 | + if (workerData === 'worker-thread-exit') { | ||
| 26 | + process.exit(0); | ||
| 27 | + } | ||
| 28 | + return; | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + (async function() { | ||
| 33 | + for (const { execArgv, variant, warnings } of [ | ||
| 34 | + { execArgv: ['--trace-exit'], variant: 'main-thread-exit', warnings: 1 }, | ||
| 35 | + { execArgv: [], variant: 'main-thread-exit', warnings: 0 }, | ||
| 36 | + { execArgv: ['--trace-exit'], variant: 'main-thread', warnings: 0 }, | ||
| 37 | + { execArgv: [], variant: 'main-thread', warnings: 0 }, | ||
| 38 | + { execArgv: ['--trace-exit'], variant: 'worker-thread-exit', warnings: 1 }, | ||
| 39 | + { execArgv: [], variant: 'worker-thread-exit', warnings: 0 }, | ||
| 40 | + { execArgv: ['--trace-exit'], variant: 'worker-thread', warnings: 0 }, | ||
| 41 | + { execArgv: [], variant: 'worker-thread', warnings: 0 }, | ||
| 42 | + ]) { | ||
| 43 | + const { stdout, stderr } = | ||
| 44 | + await execFile(process.execPath, [...execArgv, __filename, variant]); | ||
| 45 | + assert.strictEqual(stdout, ''); | ||
| 46 | + const actualWarnings = | ||
| 47 | + stderr.match(/WARNING: Exited the environment with code 0/g); | ||
| 48 | + if (warnings === 0) { | ||
| 49 | + assert.strictEqual(actualWarnings, null); | ||
| 50 | + return; | ||
| 51 | + } | ||
| 52 | + assert.strictEqual(actualWarnings.length, warnings); | ||
| 53 | + | ||
| 54 | + if (variant.startsWith('worker')) { | ||
| 55 | + const workerIds = stderr.match(/\(node:\d+, thread:\d+)/g); | ||
| 56 | + assert.strictEqual(workerIds.length, warnings); | ||
| 57 | + } | ||
| 58 | + } | ||
| 59 | + })().then(common.mustCall()); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments