lib,src,doc: add --heapsnapshot-signal CLI flag
This flag allows heap snapshots to be captured without modifying application code. PR-URL: https://github.com/nodejs/node/pull/27133 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
8cf3af1486
commit
9b6b567bc4
@ -230,6 +230,14 @@ https://github.com/tc39/ecma262/pull/1320.
|
|||||||
|
|
||||||
Both of the above may change in future updates, which will be breaking changes.
|
Both of the above may change in future updates, which will be breaking changes.
|
||||||
|
|
||||||
|
### `--heapsnapshot-signal=signal`
|
||||||
|
<!-- YAML
|
||||||
|
added: REPLACEME
|
||||||
|
-->
|
||||||
|
|
||||||
|
Generates a heap snapshot each time the process receives the specified signal.
|
||||||
|
`signal` must be a valid signal name. Disabled by default.
|
||||||
|
|
||||||
### `--http-parser=library`
|
### `--http-parser=library`
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v11.4.0
|
added: v11.4.0
|
||||||
@ -765,6 +773,7 @@ Node.js options that are allowed are:
|
|||||||
- `--experimental-vm-modules`
|
- `--experimental-vm-modules`
|
||||||
- `--force-fips`
|
- `--force-fips`
|
||||||
- `--frozen-intrinsics`
|
- `--frozen-intrinsics`
|
||||||
|
- `--heapsnapshot-signal`
|
||||||
- `--icu-data-dir`
|
- `--icu-data-dir`
|
||||||
- `--inspect`
|
- `--inspect`
|
||||||
- `--inspect-brk`
|
- `--inspect-brk`
|
||||||
|
@ -156,6 +156,9 @@ Same requirements as
|
|||||||
.It Fl -frozen-intrinsics
|
.It Fl -frozen-intrinsics
|
||||||
Enable experimental frozen intrinsics support.
|
Enable experimental frozen intrinsics support.
|
||||||
.
|
.
|
||||||
|
.It Fl -heapsnapshot-signal Ns = Ns Ar signal
|
||||||
|
Generate heap snapshot on specified signal.
|
||||||
|
.
|
||||||
.It Fl -http-parser Ns = Ns Ar library
|
.It Fl -http-parser Ns = Ns Ar library
|
||||||
Chooses an HTTP parser library. Available values are
|
Chooses an HTTP parser library. Available values are
|
||||||
.Sy llhttp
|
.Sy llhttp
|
||||||
|
@ -29,6 +29,8 @@ function prepareMainThreadExecution(expandArgv1 = false) {
|
|||||||
initializeReport();
|
initializeReport();
|
||||||
initializeReportSignalHandlers(); // Main-thread-only.
|
initializeReportSignalHandlers(); // Main-thread-only.
|
||||||
|
|
||||||
|
initializeHeapSnapshotSignalHandlers();
|
||||||
|
|
||||||
// If the process is spawned with env NODE_CHANNEL_FD, it's probably
|
// If the process is spawned with env NODE_CHANNEL_FD, it's probably
|
||||||
// spawned by our child_process module, then initialize IPC.
|
// spawned by our child_process module, then initialize IPC.
|
||||||
// This attaches some internal event listeners and creates:
|
// This attaches some internal event listeners and creates:
|
||||||
@ -166,6 +168,20 @@ function initializeReportSignalHandlers() {
|
|||||||
addSignalHandler();
|
addSignalHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initializeHeapSnapshotSignalHandlers() {
|
||||||
|
const signal = getOptionValue('--heapsnapshot-signal');
|
||||||
|
|
||||||
|
if (!signal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
require('internal/validators').validateSignalName(signal);
|
||||||
|
const { writeHeapSnapshot } = require('v8');
|
||||||
|
|
||||||
|
process.on(signal, () => {
|
||||||
|
writeHeapSnapshot();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function setupTraceCategoryState() {
|
function setupTraceCategoryState() {
|
||||||
const { isTraceCategoryEnabled } = internalBinding('trace_events');
|
const { isTraceCategoryEnabled } = internalBinding('trace_events');
|
||||||
const { toggleTraceCategoryState } = require('internal/process/per_thread');
|
const { toggleTraceCategoryState } = require('internal/process/per_thread');
|
||||||
|
@ -273,6 +273,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
|||||||
"experimental frozen intrinsics support",
|
"experimental frozen intrinsics support",
|
||||||
&EnvironmentOptions::frozen_intrinsics,
|
&EnvironmentOptions::frozen_intrinsics,
|
||||||
kAllowedInEnvironment);
|
kAllowedInEnvironment);
|
||||||
|
AddOption("--heapsnapshot-signal",
|
||||||
|
"Generate heap snapshot on specified signal",
|
||||||
|
&EnvironmentOptions::heap_snapshot_signal,
|
||||||
|
kAllowedInEnvironment);
|
||||||
AddOption("--http-parser",
|
AddOption("--http-parser",
|
||||||
"Select which HTTP parser to use; either 'legacy' or 'llhttp' "
|
"Select which HTTP parser to use; either 'legacy' or 'llhttp' "
|
||||||
"(default: llhttp).",
|
"(default: llhttp).",
|
||||||
|
@ -100,6 +100,7 @@ class EnvironmentOptions : public Options {
|
|||||||
bool experimental_vm_modules = false;
|
bool experimental_vm_modules = false;
|
||||||
bool expose_internals = false;
|
bool expose_internals = false;
|
||||||
bool frozen_intrinsics = false;
|
bool frozen_intrinsics = false;
|
||||||
|
std::string heap_snapshot_signal;
|
||||||
std::string http_parser = "llhttp";
|
std::string http_parser = "llhttp";
|
||||||
bool no_deprecation = false;
|
bool no_deprecation = false;
|
||||||
bool no_force_async_hooks_checks = false;
|
bool no_force_async_hooks_checks = false;
|
||||||
|
41
test/sequential/test-heapdump-flag.js
Normal file
41
test/sequential/test-heapdump-flag.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
|
||||||
|
if (common.isWindows)
|
||||||
|
common.skip('test not supported on Windows');
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
if (process.argv[2] === 'child') {
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
assert.strictEqual(process.listenerCount('SIGUSR2'), 1);
|
||||||
|
process.kill(process.pid, 'SIGUSR2');
|
||||||
|
process.kill(process.pid, 'SIGUSR2');
|
||||||
|
|
||||||
|
// Asynchronously wait for the snapshot. Use an async loop to be a bit more
|
||||||
|
// robust in case platform or machine differences throw off the timing.
|
||||||
|
(function validate() {
|
||||||
|
const files = fs.readdirSync(process.cwd());
|
||||||
|
|
||||||
|
if (files.length === 0)
|
||||||
|
return setImmediate(validate);
|
||||||
|
|
||||||
|
assert.strictEqual(files.length, 2);
|
||||||
|
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
assert(/^Heap\..+\.heapsnapshot$/.test(files[i]));
|
||||||
|
JSON.parse(fs.readFileSync(files[i]));
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
} else {
|
||||||
|
const { spawnSync } = require('child_process');
|
||||||
|
const tmpdir = require('../common/tmpdir');
|
||||||
|
|
||||||
|
tmpdir.refresh();
|
||||||
|
const args = ['--heapsnapshot-signal', 'SIGUSR2', __filename, 'child'];
|
||||||
|
const child = spawnSync(process.execPath, args, { cwd: tmpdir.path });
|
||||||
|
|
||||||
|
assert.strictEqual(child.status, 0);
|
||||||
|
assert.strictEqual(child.signal, null);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user