Skip to content

Commit 0e1ccbb

Browse files
authored
Fix leaking global 'uncaughtException' handler (#4147)
1 parent 7d78f20 commit 0e1ccbb

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

lib/runner.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ Runner.prototype.runSuite = function(suite, fn) {
800800
};
801801

802802
/**
803-
* Handle uncaught exceptions.
803+
* Handle uncaught exceptions within runner.
804804
*
805805
* @param {Error} err
806806
* @private
@@ -893,6 +893,17 @@ Runner.prototype.uncaught = function(err) {
893893
this.abort();
894894
};
895895

896+
/**
897+
* Handle uncaught exceptions after runner's end event.
898+
*
899+
* @param {Error} err
900+
* @private
901+
*/
902+
Runner.prototype.uncaughtEnd = function uncaughtEnd(err) {
903+
if (err instanceof Pending) return;
904+
throw err;
905+
};
906+
896907
/**
897908
* Run the root suite and invoke `fn(failures)`
898909
* on completion.
@@ -940,16 +951,12 @@ Runner.prototype.run = function(fn) {
940951
this.on(constants.EVENT_RUN_END, function() {
941952
debug(constants.EVENT_RUN_END);
942953
process.removeListener('uncaughtException', uncaught);
943-
process.on('uncaughtException', function(err) {
944-
if (err instanceof Pending) {
945-
return;
946-
}
947-
throw err;
948-
});
954+
process.on('uncaughtException', self.uncaughtEnd);
949955
fn(self.failures);
950956
});
951957

952958
// uncaught exception
959+
process.removeListener('uncaughtException', self.uncaughtEnd);
953960
process.on('uncaughtException', uncaught);
954961

955962
if (this._delay) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const mocha = require("../../../../lib/mocha");
5+
6+
for (let i = 0; i < 15; i++) {
7+
const r = new mocha.Runner(new mocha.Suite("" + i, undefined));
8+
r.run();
9+
}
10+
11+
assert.equal(process.listenerCount('uncaughtException'), 1);
12+
assert.equal(process.listeners('uncaughtException')[0].name, 'uncaughtEnd');

test/integration/uncaught.spec.js

+12
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,16 @@ describe('uncaught exceptions', function() {
8686
done();
8787
});
8888
});
89+
90+
it('removes uncaught exceptions handlers correctly', function(done) {
91+
run('uncaught/listeners.fixture.js', args, function(err, res) {
92+
if (err) {
93+
return done(err);
94+
}
95+
96+
expect(res, 'to have passed').and('to have passed test count', 0);
97+
98+
done();
99+
});
100+
});
89101
});

0 commit comments

Comments
 (0)