summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-04-08 10:20:26 -0400
committercjihrig <cjihrig@gmail.com>2019-04-12 17:16:46 -0400
commit9b6b567bc4dd8f40bad12528eebf12dac8a8027f (patch)
tree7e2b9264a4d45f26091f92c099065320abd47f75
parent8cf3af14864ac1bee4b3145bec8a8cf3e38edc55 (diff)
downloadandroid-node-v8-9b6b567bc4dd8f40bad12528eebf12dac8a8027f.tar.gz
android-node-v8-9b6b567bc4dd8f40bad12528eebf12dac8a8027f.tar.bz2
android-node-v8-9b6b567bc4dd8f40bad12528eebf12dac8a8027f.zip
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>
-rw-r--r--doc/api/cli.md9
-rw-r--r--doc/node.13
-rw-r--r--lib/internal/bootstrap/pre_execution.js16
-rw-r--r--src/node_options.cc4
-rw-r--r--src/node_options.h1
-rw-r--r--test/sequential/test-heapdump-flag.js41
6 files changed, 74 insertions, 0 deletions
diff --git a/doc/api/cli.md b/doc/api/cli.md
index ced8cece1d..60d75a6c04 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -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.
+### `--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`
<!-- YAML
added: v11.4.0
@@ -765,6 +773,7 @@ Node.js options that are allowed are:
- `--experimental-vm-modules`
- `--force-fips`
- `--frozen-intrinsics`
+- `--heapsnapshot-signal`
- `--icu-data-dir`
- `--inspect`
- `--inspect-brk`
diff --git a/doc/node.1 b/doc/node.1
index e2ac998cab..0fccabc4bc 100644
--- a/doc/node.1
+++ b/doc/node.1
@@ -156,6 +156,9 @@ Same requirements as
.It Fl -frozen-intrinsics
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
Chooses an HTTP parser library. Available values are
.Sy llhttp
diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js
index e2b1103f8c..6b1e3fb213 100644
--- a/lib/internal/bootstrap/pre_execution.js
+++ b/lib/internal/bootstrap/pre_execution.js
@@ -29,6 +29,8 @@ function prepareMainThreadExecution(expandArgv1 = false) {
initializeReport();
initializeReportSignalHandlers(); // Main-thread-only.
+ initializeHeapSnapshotSignalHandlers();
+
// If the process is spawned with env NODE_CHANNEL_FD, it's probably
// spawned by our child_process module, then initialize IPC.
// This attaches some internal event listeners and creates:
@@ -166,6 +168,20 @@ function initializeReportSignalHandlers() {
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() {
const { isTraceCategoryEnabled } = internalBinding('trace_events');
const { toggleTraceCategoryState } = require('internal/process/per_thread');
diff --git a/src/node_options.cc b/src/node_options.cc
index 8463765eb6..c307c66a62 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -273,6 +273,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
"experimental frozen intrinsics support",
&EnvironmentOptions::frozen_intrinsics,
kAllowedInEnvironment);
+ AddOption("--heapsnapshot-signal",
+ "Generate heap snapshot on specified signal",
+ &EnvironmentOptions::heap_snapshot_signal,
+ kAllowedInEnvironment);
AddOption("--http-parser",
"Select which HTTP parser to use; either 'legacy' or 'llhttp' "
"(default: llhttp).",
diff --git a/src/node_options.h b/src/node_options.h
index e07ee7fb35..59baea562a 100644
--- a/src/node_options.h
+++ b/src/node_options.h
@@ -100,6 +100,7 @@ class EnvironmentOptions : public Options {
bool experimental_vm_modules = false;
bool expose_internals = false;
bool frozen_intrinsics = false;
+ std::string heap_snapshot_signal;
std::string http_parser = "llhttp";
bool no_deprecation = false;
bool no_force_async_hooks_checks = false;
diff --git a/test/sequential/test-heapdump-flag.js b/test/sequential/test-heapdump-flag.js
new file mode 100644
index 0000000000..65401b9d71
--- /dev/null
+++ b/test/sequential/test-heapdump-flag.js
@@ -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);
+}