summaryrefslogtreecommitdiff
path: root/test/parallel/test-domain-abort-on-uncaught.js
diff options
context:
space:
mode:
authorJulien Gilli <julien.gilli@joyent.com>2015-11-02 17:56:24 -0800
committerJulien Gilli <julien.gilli@joyent.com>2015-12-11 14:33:48 -0800
commit425a3545d26bdc0b17115bc84101191c59b0553f (patch)
tree8372ff5a2882a8e2d84ae729d98e040a0eecfea6 /test/parallel/test-domain-abort-on-uncaught.js
parent1a21a5368bab50548203970cedb318f421f4fba3 (diff)
downloadandroid-node-v8-425a3545d26bdc0b17115bc84101191c59b0553f.tar.gz
android-node-v8-425a3545d26bdc0b17115bc84101191c59b0553f.tar.bz2
android-node-v8-425a3545d26bdc0b17115bc84101191c59b0553f.zip
domains: fix handling of uncaught exceptions
Fix node exiting due to an exception being thrown rather than emitting an `'uncaughtException'` event on the process object when: 1. no error handler is set on the domain within which an error is thrown 2. an `'uncaughtException'` event listener is set on the process Also fix an issue where the process would not abort in the proper function call if an error is thrown within a domain with no error handler and `--abort-on-uncaught-exception` is used. Finally, change the behavior of --abort-on-uncaught-exception so that, if the domain within which the error is thrown has no error handler, but a domain further up the domains stack has one, the process will not abort. Fixes #3607 and #3653. PR: #3654 PR-URL: https://github.com/nodejs/node/pull/3654 Reviewed-By: Chris Dickinson <chris@neversaw.us>
Diffstat (limited to 'test/parallel/test-domain-abort-on-uncaught.js')
-rw-r--r--test/parallel/test-domain-abort-on-uncaught.js310
1 files changed, 235 insertions, 75 deletions
diff --git a/test/parallel/test-domain-abort-on-uncaught.js b/test/parallel/test-domain-abort-on-uncaught.js
index f4884aa8f3..9d23046506 100644
--- a/test/parallel/test-domain-abort-on-uncaught.js
+++ b/test/parallel/test-domain-abort-on-uncaught.js
@@ -1,96 +1,256 @@
'use strict';
-// Flags: --abort_on_uncaught_exception
-
-var common = require('../common');
-var assert = require('assert');
-var domain = require('domain');
-
-var tests = [
- nextTick,
- timer,
- timerPlusNextTick,
- netServer,
- firstRun,
-];
-var errors = 0;
+// This test makes sure that when using --abort-on-uncaught-exception and
+// when throwing an error from within a domain that has an error handler
+// setup, the process _does not_ abort.
-process.on('exit', function() {
- assert.equal(errors, tests.length);
-});
+const common = require('../common');
+const assert = require('assert');
+const domain = require('domain');
+const child_process = require('child_process');
-tests.forEach(function(test) { test(); });
+var errorHandlerCalled = false;
-function nextTick() {
- var d = domain.create();
+const tests = [
+ function nextTick() {
+ const d = domain.create();
- d.once('error', function(err) {
- errors += 1;
- });
- d.run(function() {
- process.nextTick(function() {
- throw new Error('exceptional!');
+ d.once('error', function(err) {
+ errorHandlerCalled = true;
});
- });
-}
-function timer() {
- var d = domain.create();
+ d.run(function() {
+ process.nextTick(function() {
+ throw new Error('exceptional!');
+ });
+ });
+ },
- d.on('error', function(err) {
- errors += 1;
- });
- d.run(function() {
- setTimeout(function() {
- throw new Error('exceptional!');
- }, 33);
- });
-}
+ function timer() {
+ const d = domain.create();
-function timerPlusNextTick() {
- var d = domain.create();
+ d.on('error', function(err) {
+ errorHandlerCalled = true;
+ });
- d.on('error', function(err) {
- errors += 1;
- });
- d.run(function() {
- setTimeout(function() {
- process.nextTick(function() {
+ d.run(function() {
+ setTimeout(function() {
throw new Error('exceptional!');
+ }, 33);
+ });
+ },
+
+ function immediate() {
+ const d = domain.create();
+
+ d.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ setImmediate(function() {
+ throw new Error('boom!');
});
- }, 33);
- });
-}
+ });
+ },
-function firstRun() {
- var d = domain.create();
+ function timerPlusNextTick() {
+ const d = domain.create();
- d.on('error', function(err) {
- errors += 1;
- });
- d.run(function() {
- throw new Error('exceptional!');
- });
-}
+ d.on('error', function(err) {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ setTimeout(function() {
+ process.nextTick(function() {
+ throw new Error('exceptional!');
+ });
+ }, 33);
+ });
+ },
-function netServer() {
- var net = require('net');
- var d = domain.create();
+ function firstRun() {
+ const d = domain.create();
- d.on('error', function(err) {
- errors += 1;
- });
- d.run(function() {
- var server = net.createServer(function(conn) {
- conn.pipe(conn);
- });
- server.listen(common.PORT, '0.0.0.0', function() {
- var conn = net.connect(common.PORT, '0.0.0.0');
- conn.once('data', function() {
- throw new Error('ok');
+ d.on('error', function(err) {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ throw new Error('exceptional!');
+ });
+ },
+
+ function fsAsync() {
+ const d = domain.create();
+
+ d.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ var fs = require('fs');
+ fs.exists('/non/existing/file', function onExists(exists) {
+ throw new Error('boom!');
+ });
+ });
+ },
+
+ function netServer() {
+ const net = require('net');
+ const d = domain.create();
+
+ d.on('error', function(err) {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ const server = net.createServer(function(conn) {
+ conn.pipe(conn);
+ });
+ server.listen(common.PORT, common.localhostIPv4, function() {
+ const conn = net.connect(common.PORT, common.localhostIPv4);
+ conn.once('data', function() {
+ throw new Error('ok');
+ });
+ conn.end('ok');
+ server.close();
});
- conn.end('ok');
- server.close();
+ });
+ },
+
+ function firstRunOnlyTopLevelErrorHandler() {
+ const d = domain.create();
+ const d2 = domain.create();
+
+ d.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ d2.run(function() {
+ throw new Error('boom!');
+ });
+ });
+ },
+
+ function firstRunNestedWithErrorHandler() {
+ const d = domain.create();
+ const d2 = domain.create();
+
+ d2.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ d2.run(function() {
+ throw new Error('boom!');
+ });
+ });
+ },
+
+ function timeoutNestedWithErrorHandler() {
+ const d = domain.create();
+ const d2 = domain.create();
+
+ d2.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ d2.run(function() {
+ setTimeout(function() {
+ console.log('foo');
+ throw new Error('boom!');
+ }, 33);
+ });
+ });
+ },
+
+ function setImmediateNestedWithErrorHandler() {
+ const d = domain.create();
+ const d2 = domain.create();
+
+ d2.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ d2.run(function() {
+ setImmediate(function() {
+ throw new Error('boom!');
+ });
+ });
+ });
+ },
+
+ function nextTickNestedWithErrorHandler() {
+ const d = domain.create();
+ const d2 = domain.create();
+
+ d2.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ d2.run(function() {
+ process.nextTick(function() {
+ throw new Error('boom!');
+ });
+ });
+ });
+ },
+
+ function fsAsyncNestedWithErrorHandler() {
+ const d = domain.create();
+ const d2 = domain.create();
+
+ d2.on('error', function errorHandler() {
+ errorHandlerCalled = true;
+ });
+
+ d.run(function() {
+ d2.run(function() {
+ var fs = require('fs');
+ fs.exists('/non/existing/file', function onExists(exists) {
+ throw new Error('boom!');
+ });
+ });
+ });
+ }
+];
+
+if (process.argv[2] === 'child') {
+ const testIndex = +process.argv[3];
+
+ tests[testIndex]();
+
+ process.on('exit', function onExit() {
+ assert.equal(errorHandlerCalled, true);
+ });
+} else {
+
+ tests.forEach(function(test, testIndex) {
+ var testCmd = '';
+ if (process.platform !== 'win32') {
+ // Do not create core files, as it can take a lot of disk space on
+ // continuous testing and developers' machines
+ testCmd += 'ulimit -c 0 && ';
+ }
+
+ testCmd += process.argv[0];
+ testCmd += ' ' + '--abort-on-uncaught-exception';
+ testCmd += ' ' + process.argv[1];
+ testCmd += ' ' + 'child';
+ testCmd += ' ' + testIndex;
+
+ var child = child_process.exec(testCmd);
+
+ child.on('exit', function onExit(code, signal) {
+ assert.equal(code, 0, 'Test at index ' + testIndex +
+ ' should have exited with exit code 0 but instead exited with code ' +
+ code + ' and signal ' + signal);
});
});
}