Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catch all `error` events from any EventEmitter in node

Tags:

node.js

Via the Node.js documentation, an unhandled EventEmitter will crash a running process:

When an EventEmitter instance experiences an error, the typical action is to emit an 'error' event. Error events are treated as a special case in node. If there is no listener for it, then the default action is to print a stack trace and exit the program.

I would very much like for the process to not crash when this happens.[1] Ideally, I could catch every instance of an EventEmitter error like this:

emitter.on('error', function(err) { console.log(err); })

However our application is large, a simple search of the node_modules folder reveals that there are lots of EventEmitters, and tracking them down would be cumbersome.

Is there a global hook I can use to catch all instances of an EventEmitter failure?

I tried process.on('uncaughtException') but this doesn't catch EventEmitter errors. I also tried process.on('error') which catches errors emitted by the process, but does not catch errors emitted by other EventEmitters.

Other places say you should use domains, however, it sounds like you need to wrap specific function calls in it, at which point you might as well find and wrap every EventEmitter with .on('error'). My colleague also says domains are, if not deprecated, not going to be used going forward.

[1] I understand the logic behind the "processes should crash" argument. Partly I would like to keep processes alive because a) our server takes a long time to restart, and b) processes keep crashing with literally zero stack trace; I figure keeping the process alive will help with logging and tracking down errors.

like image 444
Kevin Burke Avatar asked Mar 30 '15 23:03

Kevin Burke


1 Answers

process.on('uncaughtException', ...) does catch EventEmittor errors. Try this:

'use strict';

setInterval(function () {}, Number.MAX_VALUE); // keep process alive

var myEmitter = new (require('events').EventEmitter)();

// add this handler before emitting any events
process.on('uncaughtException', function (err) {
    console.log('UNCAUGHT EXCEPTION - keeping process alive:', err); // err.message is "foobar"
});

myEmitter.emit('error', new Error('foobar'));

Note that if you add the uncaughtException listener after your error event has fired, the exception won't get caught!

like image 85
borisdiakur Avatar answered Sep 21 '22 04:09

borisdiakur