summaryrefslogtreecommitdiff
path: root/test/abort
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2018-06-07 22:07:02 +0200
committerAnna Henningsen <anna@addaleax.net>2018-06-13 12:23:36 +0200
commitaa2304b8d5c53ba2d9710d8b8ed4482f3cbd1192 (patch)
tree4bd93c9dd7f8a5fa0e04c4897b8e0aa7c1075225 /test/abort
parent8e2d33f15620013de504c1181641aa961906f436 (diff)
downloadandroid-node-v8-aa2304b8d5c53ba2d9710d8b8ed4482f3cbd1192.tar.gz
android-node-v8-aa2304b8d5c53ba2d9710d8b8ed4482f3cbd1192.tar.bz2
android-node-v8-aa2304b8d5c53ba2d9710d8b8ed4482f3cbd1192.zip
worker,src: display remaining handles if `uv_loop_close` fails
Right now, we crash the process if there are handles remaining on the event loop when we exit (except for the main thread). This does not provide a lot of information about causes, though; in particular, we don’t show which handles are pending and who own them. This patch adds debug output to these cases to help with the situation. PR-URL: https://github.com/nodejs/node/pull/21238 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'test/abort')
-rw-r--r--test/abort/test-addon-uv-handle-leak.js97
1 files changed, 97 insertions, 0 deletions
diff --git a/test/abort/test-addon-uv-handle-leak.js b/test/abort/test-addon-uv-handle-leak.js
new file mode 100644
index 0000000000..3944cb79c7
--- /dev/null
+++ b/test/abort/test-addon-uv-handle-leak.js
@@ -0,0 +1,97 @@
+// Flags: --experimental-worker
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const fs = require('fs');
+const path = require('path');
+const cp = require('child_process');
+const { Worker } = require('worker_threads');
+
+// This is a sibling test to test/addons/uv-handle-leak.
+
+const bindingPath = path.resolve(
+ __dirname, '..', 'addons', 'uv-handle-leak', 'build',
+ `${common.buildType}/binding.node`);
+
+if (!fs.existsSync(bindingPath))
+ common.skip('binding not built yet');
+
+if (process.argv[2] === 'child') {
+ new Worker(`
+ const binding = require(${JSON.stringify(bindingPath)});
+
+ binding.leakHandle();
+ binding.leakHandle(0);
+ binding.leakHandle(0x42);
+ `, { eval: true });
+} else {
+ const child = cp.spawnSync(process.execPath,
+ ['--experimental-worker', __filename, 'child']);
+ const stderr = child.stderr.toString();
+
+ assert.strictEqual(child.stdout.toString(), '');
+
+ const lines = stderr.split('\n');
+
+ let state = 'initial';
+
+ // parse output that is formatted like this:
+
+ // uv loop at [0x559b65ed5770] has active handles
+ // [0x7f2de0018430] timer
+ // Close callback: 0x7f2df31de220 CloseCallback(uv_handle_s*) [...]
+ // Data: 0x7f2df33df140 example_instance [...]
+ // (First field): 0x7f2df33dedc0 vtable for ExampleOwnerClass [...]
+ // [0x7f2de000b870] timer
+ // Close callback: 0x7f2df31de220 CloseCallback(uv_handle_s*) [...]
+ // Data: (nil)
+ // [0x7f2de000b910] timer
+ // Close callback: 0x7f2df31de220 CloseCallback(uv_handle_s*) [...]
+ // Data: 0x42
+
+ if (!(common.isFreeBSD ||
+ common.isAIX ||
+ (common.isLinux && !common.isGlibc()) ||
+ common.isWindows)) {
+ assert(stderr.includes('ExampleOwnerClass'), stderr);
+ assert(stderr.includes('CloseCallback'), stderr);
+ assert(stderr.includes('example_instance'), stderr);
+ }
+
+ while (lines.length > 0) {
+ const line = lines.shift().trim();
+
+ switch (state) {
+ case 'initial':
+ assert(/^uv loop at \[.+\] has active handles$/.test(line), line);
+ state = 'handle-start';
+ break;
+ case 'handle-start':
+ if (/Assertion .+ failed/.test(line)) {
+ state = 'done';
+ break;
+ }
+ assert(/^\[.+\] timer$/.test(line), line);
+ state = 'close-callback';
+ break;
+ case 'close-callback':
+ assert(/^Close callback:/.test(line), line);
+ state = 'data';
+ break;
+ case 'data':
+ assert(/^Data: .+$/.test(line), line);
+ state = 'maybe-first-field';
+ break;
+ case 'maybe-first-field':
+ if (/^\(First field\)$/.test(line)) {
+ lines.unshift(line);
+ state = 'handle-start';
+ break;
+ }
+ state = 'maybe-first-field';
+ break;
+ case 'done':
+ break;
+ }
+ }
+}