обнаружена возможная утечка памяти EventEmitter

Я получаю следующее предупреждение:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at EventEmitter.<anonymous> (events.js:139:15)
    at EventEmitter.<anonymous> (node.js:385:29)
    at Server.<anonymous> (server.js:20:17)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1514:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)
    at Socket.ondata (http.js:1410:22)
    at TCP.onread (net.js:354:27)

Я написал такой код на сервере.js:

http.createServer(
    function (req, res) { ... }).listen(3013);

Как это исправить ?

15 ответов


Это объясняется в руководстве: http://nodejs.org/docs/latest/api/events.html#events_emitter_setmaxlisteners_n

что это за Версия Node? Какой еще код у вас есть? Это ненормальное поведение.

в: process.setMaxListeners(0);

Смотрите также: узел.js-request-как "излучатель.setMaxListeners ()"?


Я хотел бы указать здесь, что это предупреждение существует по какой-то причине, и есть хороший шанс, что правильное исправление не увеличение предела, но выяснить, почему вы добавляете так много слушателей к тому же событию. Только увеличить предел, если вы знаете, почему так много слушателей добавляются и уверены, что это то, что вы действительно хотите.

Я нашел эту страницу, потому что я получил это предупреждение, и в моем случае была ошибка в некотором коде, который я использовал, что превращал глобальный объект в EventEmitter! Я бы, конечно, не советовал увеличивать лимит по всему миру, потому что вы не хотите, чтобы эти вещи остались незамеченными.


по умолчанию для любого события может быть зарегистрировано не более 10 слушателей.

если это ваш код, вы можете указать maxListeners через:

const emitter = new EventEmitter()
emitter.setMaxListeners(100)
// or 0 to turn off the limit
emitter.setMaxListeners(0)

но если это не ваш код вы можете использовать трюк, чтобы увеличить лимит по умолчанию глобально:

require('events').EventEmitter.prototype._maxListeners = 100;

конечно, вы можете отключить ограничения, но будьте осторожны:

// turn off limits by default (BE CAREFUL)
require('events').EventEmitter.prototype._maxListeners = 0;

кстати. Код должен быть в самом начале приложения.

ADD: поскольку узел 0.11 этот код также работает изменить ограничение по умолчанию:

require('events').EventEmitter.defaultMaxListeners = 0

принятый ответ предоставляет семантику о том, как увеличить предел, но, как отметил @voltrevo, предупреждение существует по какой-то причине, и ваш код, вероятно, имеет ошибку.

рассмотрим следующий код багги:

//Assume Logger is a module that emits errors
var Logger = require('./Logger.js');

for (var i = 0; i < 11; i++) {
    //BUG: This will cause the warning
    //As the event listener is added in a loop
    Logger.on('error', function (err) {
        console.log('error writing log: ' + err)
    });

    Logger.writeLog('Hello');
}

теперь обратите внимание на правильный способ добавления слушателя:

//Good: event listener is not in a loop
Logger.on('error', function (err) {
    console.log('error writing log: ' + err)
});

for (var i = 0; i < 11; i++) {
    Logger.writeLog('Hello');
}

поиск аналогичных проблем в коде перед изменением maxListeners (что объясняется в других ответах)


заменить .на() раз(). использование once () удаляет прослушиватели событий, когда событие обрабатывается той же функцией. источник: http://nodeguide.com/beginner.html#using-eventemitters

Если это не исправить, то переустановите restler с этим в вашем пакете.формат JSON "restler": "в git://github-е. ком/danwrong/restler.в Git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d"

Это связано с неправильным поведением restler 0.10 с узлом. можно посмотреть вопрос закрыт git здесь:https://github.com/danwrong/restler/issues/112 однако npm еще не обновил это, поэтому вам нужно обратиться к главе git.

счастливый restling:)


Я тоже получаю это предупреждение при установке aglio на моем mac osx.

Я использую cmd исправить это.

sudo npm install -g npm@next

https://github.com/npm/npm/issues/13806


в моем случае, это был child.stderr.pipe(process.stderr) который вызывался, когда я инициировал 10 (или около того) экземпляров ребенка. Так что все, что приводит к присоединению обработчика событий к тому же объекту EventEmitter в цикле, заставляет nodejs выдавать эту ошибку.


иногда эти предупреждения происходят, когда это не то, что мы сделали, но то, что мы забыли сделать!

Я столкнулся с этим предупреждением, когда я установил пакет dotenv с npm, но был прерван, прежде чем я добрался до добавления require('dotenv').инструкция load() в начале моего приложения. Когда я вернулся в проект, я начал получать предупреждения "возможная утечка памяти EventEmitter обнаружена".

Я предположил, что проблема в чем-то, что у меня было сделано, а не то, чего не делал я!

Как только я обнаружил свою оплошность и добавил оператор require, предупреждение об утечке памяти очистилось.


у меня было это до сегодняшнего дня, когда я начинаю grunt watch. Наконец решена

watch:{
        options:{
            maxListeners: 99,
            livereload: true
        },
}

раздражающее сообщение исчезло.


Вы сказали, что вы используете process.on('uncaughtException', callback);
Где вы выполняете это заявление? Это в пределах обратного вызова, переданного http.createServer?
если да, другая копия того же обратного вызова будет прикреплена к uncaughtException событие при каждом новом запросе, потому что function (req, res) { ... } выполняется каждый раз, когда приходит новый запрос, а также оператор process.on('uncaughtException', callback);
отметим, что объект процесса является глобальным для всех ваших запросов и добавления слушателей к его событию каждый раз, когда приходит новая просьба, в ней нет никакого смысла. Возможно, ты не захочешь такого поведения.
в случае, если вы хотите прикрепить новый слушатель для каждого нового запроса, вы должны удалить все предыдущие слушатели, прикрепленные к событию, поскольку они больше не будут необходимы, используя:
process.removeAllListeners('uncaughtException');


исправление нашей команды для этого было удаление пути реестра из нашего .npmrc. У нас было два псевдонима пути в файле rc, и один указывал на искусственный экземпляр, который был устаревшим.

ошибка не имела ничего общего с фактическим кодом нашего приложения, но все сделать с нашей средой разработки.


У меня была та же проблема. и проблема была вызвана тем, что я слушал порт 8080, на 2 слушателей.

setMaxListeners() работает нормально, но я бы не советовал.

правильный способ-проверить код на наличие дополнительных прослушивателей, удалить прослушиватель или изменить номер порта, на котором вы слушаете, это исправило мою проблему.


я обновил старую версию LTS, 6 что-то, до новой версии LTS 8.9.4, и мои ошибки исчезли.


Я предпочитаю выслеживать и исправлять проблемы вместо подавления журналов, когда это возможно. Через пару дней наблюдения за этой проблемой в моем приложении я понял, что устанавливаю слушателей на req.socket в экспресс-промежуточном по, чтобы поймать ошибки ввода-вывода сокета, которые продолжали появляться. В какой-то момент я понял, что в этом нет необходимости, но все равно держал слушателей поблизости. Я просто удалил их, и ошибка, которую вы испытываете, ушла. Я проверил, что это было причиной, запустив запросы на мой сервер со следующим промежуточным ПО и без него:

socketEventsHandler(req, res, next) {
        req.socket.on("error", function(err) {
            console.error('------REQ ERROR')
            console.error(err.stack)
        });
        res.socket.on("error", function(err) {
            console.error('------RES ERROR')
            console.error(err.stack)
        });
        next();
    }

удаление этого промежуточного ПО остановило предупреждение, которое вы видите. Я бы посмотрел ваш код и попытался найти где-нибудь, где вы можете настроить слушателей, которые вам не нужны.


поместите это в первую строку вашего сервера.js (или все, что содержит ваш основной узел.приложение на JS):

require('events').EventEmitter.prototype._maxListeners = 0;

и ошибка исчезнет :)