From 9da75f39d978c7b2ef1e7ba3a308bbf6f6769b72 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Fri, 31 Dec 2010 18:32:52 -0800 Subject: [PATCH] Print error when EventEmitters get too many listeners --- doc/api/events.markdown | 8 ++++++++ lib/events.js | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/api/events.markdown b/doc/api/events.markdown index e069559bbd..5749b58c1d 100644 --- a/doc/api/events.markdown +++ b/doc/api/events.markdown @@ -61,6 +61,14 @@ Remove a listener from the listener array for the specified event. Removes all listeners from the listener array for the specified event. +#### emitter.setMaxListeners(n) + +By default EventEmitters will print a warning if more than 10 listeners are +added to it. This is a useful default which helps finding memory leaks. +Obviously not all Emitters should be limited to 10. This function allows +that to be increased. Set to zero for unlimited. + + #### emitter.listeners(event) Returns an array of listeners for the specified event. This array can be diff --git a/lib/events.js b/lib/events.js index ad3ce726c7..6505606b4e 100644 --- a/lib/events.js +++ b/lib/events.js @@ -1,7 +1,18 @@ var EventEmitter = exports.EventEmitter = process.EventEmitter; - var isArray = Array.isArray; +// By default EventEmitters will print a warning if more than +// 10 listeners are added to it. This is a useful default which +// helps finding memory leaks. +// +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +var defaultMaxListeners = 10; +EventEmitter.prototype.setMaxListeners = function(n) { + this._events.maxListeners = n; +}; + + EventEmitter.prototype.emit = function(type) { // If there is no 'error' event listener then throw. if (type === 'error') { @@ -71,6 +82,26 @@ EventEmitter.prototype.addListener = function(type, listener) { // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; } else if (isArray(this._events[type])) { + + // Check for listener leak + if (!this._events[type].warned) { + var m; + if (this._events.maxListeners !== undefined) { + m = this._events.maxListeners; + } else { + m = defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + console.trace(); + } + } + // If we've already got an array, just append. this._events[type].push(listener); } else {