Comment puis-je déboguer mon application qui génère cette erreur:
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at Socket.EventEmitter.addListener (events.js:160:15)
at Socket.Readable.on (_stream_readable.js:653:33)
at Socket.EventEmitter.once (events.js:179:8)
at TCP.onread (net.js:527:26)
Je n'ai pas pu trouver l'objet supposé qui fuit pour augmenter la limite d'écoute de .setMaxListeners(0);
SOLUTION (de fardjad et jan salawa)
Avec les recherches de jan salawa, j'ai trouvé une bibliothèque de travail ( longjohn ) pour des traces de pile croissantes. Avec la réponse de fardjad, j'ai constaté qu'il nous fallait prototyper EventEmitter.addListener
[~ # ~] et [~ # ~] EventEmitter.on
.
Avec la solution, je pourrais obtenir cette nouvelle trace:
(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
at EventEmitter.addListener.EventEmitter.on (xxx/main.js:44:15)
at Readable.on (_stream_readable.js:653:33)
at ServerResponse.assignSocket (http.js:1072:10)
at parser.onIncoming (http.js:1979:11)
at parserOnHeadersComplete (http.js:119:23)
at socket.ondata (http.js:1912:22)
at TCP.onread (net.js:510:27)
Il s’avère qu’il s’agit d’un bogue dans le noeud nodejs; nous parlons de ce problème ici: https://github.com/joyent/node/issues/5108
Solution pour les serveurs http avec bogues qui jettent un EventEmitter memory leak detected
et remplissez la mémoire disponible/les temps de calcul disponibles:
Revenir à la version héritée v0.8.23
. (Vous pouvez télécharger et installer/compiler à partir d'ici: http://blog.nodejs.org/2013/04/08/node-v0-8-23-legacy/ )
UPDATE 2018: Je vois plusieurs retours sur ce sujet alors que le problème semble avoir disparu depuis des années. Notez que cette réponse est uniquement pour un serveur http qui fuit construit avec nodejs . Si vous êtes dans un autre scénario, consultez les réponses des autres sur ce fil et ne rétrogradez pas votre version (comme suggéré dans cette réponse), vous perdrez votre temps.
Pour moi, il semblerait que votre boucle d'événement soit bloquée. Cela peut se produire si vous effectuez des tâches intensives en CPU dans la boucle d'événements node.js. Vous pouvez utiliser processus enfant pour effectuer une tâche intensive.
Vous pouvez vérifier ce qui bloque node.js en utilisant méthodes suivantes :
function timeTick() {
var startTime = (new Date().getTime());
function onTick() {
var interval = (new Date().getTime()) - startTime;
if(interval > 5)
console.log('timeTick(): WARNING: interval = ' + interval);
}
process.nextTick(onTick);
}
setInterval(timeTick, 1000);
C'est exactement ce qui m'est arrivé. Pour moi, j'ai imbriqué accidentellement un auditeur d'événement dans un autre écouteur d'événement.
Examinez votre code et assurez-vous de NE PAS disposer de bloc d'écoute d'événement DANS UN autre bloc d'écoute d'événement, par exemple (sauf si vous le faites exprès):
socket.on('data', function(data) {
//code goes here
socket.on('close' , function() {
//code goes here
});
});
Dans le mauvais exemple ci-dessus, l'écouteur socket.on ('close') doit être OUTSIDE du bloc socket.on ('data').
Dans mon cas, lorsque j'ai reçu 5 flux de données, l'écouteur socket.on ('close') attend qu'un événement close se produise. Lorsque je ferme une fois, un autre 4ème événement de clôture sera exécuté. Ce n'est clairement pas ce que je voulais. Ceci est dû à la nature de Node.js qui est non bloquante. Il "se souvient" des événements en raison de la fonction de rappel.
J'ai essayé de prototyper EventEmitter pour ajouter des messages de journal dans addListener mais je ne pouvais pas le faire fonctionner
Pour accrocher addListener
, vous pouvez faire quelque chose comme ceci:
// on the first line of your main script
var events = require("events"),
EventEmitter = events.EventEmitter;
var originalAddListener = EventEmitter.prototype.addListener;
EventEmitter.prototype.addListener = function (type, listener) {
if (this.listenerCount(this, type) >= 10) {
// TODO: PLACE YOUR CODE FOR DEBUGGING HERE
}
originalAddListener.apply(this, arguments);
}
Cet avertissement sera émis si vous vous inscrivez à un événement particulier du même objet plus de 11 fois.
Vérifiez si vous rencontrez un appel "on" pour un événement particulier dans une fonction que vous appelez fréquemment. Cela conduit à vous inscrire à un événement plusieurs fois.
Ce le lien m'a aidé à comprendre cela.
Depuis le noeud 6, vous devriez utiliser node --trace-warnings
: https://nodejs.org/api/cli.html#cli_trace_warnings
Je voyais cela quand j'exécutais mes tests unitaires. Mes tests unitaires ont appelé à plusieurs reprises le code qui appelait:
process.on("uncaughtException", () => { ... });
J'ai dû utiliser l'injection de dépendance pour injecter un faux processus, ce qui a résolu le problème.
main.js:
export function main(myProcess) {
myProcess.on("uncaughtException", () => { ... });
}
if (require.main === module) { // to prevent this from executing when running unit tests
main(process);
}
Mes tests unitaires feraient:
const fakeProcess = jasmine.createSpy("process", ["on"]);
main(fakeProcess);