development

가능한 EventEmitter 메모리 누출 감지

big-blog 2020. 5. 12. 19:05
반응형

가능한 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)

server.js에 다음과 같은 코드를 작성했습니다.

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

이 문제를 해결하는 방법?


이것은 매뉴얼에 설명되어 있습니다 : http://nodejs.org/docs/latest/api/events.html#events_emitter_setmaxlisteners_n

어떤 버전의 노드입니까? 다른 코드가 있습니까? 그것은 정상적인 행동이 아닙니다.

요컨대, process.setMaxListeners(0);

참조 : node.js-요청-“emitter.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;

BTW. 코드는 앱의 시작 부분에 있어야합니다.

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를 변경하기 전에 코드에서 비슷한 문제를 검색하십시오 (다른 답변에서 설명 함).


교체 .on()와 함께 once(). 를 사용 once()하면 이벤트가 동일한 기능으로 처리 될 때 이벤트 리스너가 제거됩니다. 출처 : http://nodeguide.com/beginner.html#using-eventemitters

이 방법으로 문제가 해결되지 않으면 package.json "restler"에 "rest : //"를 설치하십시오. "git : //github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d"

This has to do with restler 0.10 misbehaving with node. you can see the issue closed on git here: https://github.com/danwrong/restler/issues/112 However, npm has yet to update this, so that is why you have to refer to the git head.


I am getting this warning too when install aglio on my mac osx.

I use cmd fix it.

sudo npm install -g npm@next

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


In my case, it was child.stderr.pipe(process.stderr) which was being called when I was initiating 10 (or so) instances of the child. So anything, that leads to attach an event handler to the same EventEmitter Object in a LOOP, causes nodejs to throw this error.


Sometimes these warnings occur when it isn't something we've done, but something we've forgotten to do!

I encountered this warning when I installed the dotenv package with npm, but was interrupted before I got around to adding the require('dotenv').load() statement at the beginning of my app. When I returned to the project, I started getting the "Possible EventEmitter memory leak detected" warnings.

I assumed the problem was from something I had done, not something I had not done!

Once I discovered my oversight and added the require statement, the memory leak warning cleared.


I prefer to hunt down and fix problems instead of suppressing logs whenever possible. After a couple days of observing this issue in my app, I realized I was setting listeners on the req.socket in an Express middleware to catch socket io errors that kept popping up. At some point, I learned that that was not necessary, but I kept the listeners around anyway. I just removed them and the error you are experiencing went away. I verified it was the cause by running requests to my server with and without the following middleware:

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();
    }

Removing that middleware stopped the warning you are seeing. I would look around your code and try to find anywhere you may be setting up listeners that you don't need.


i was having the same problem. and the problem was caused because i was listening to port 8080, on 2 listeners.

setMaxListeners() works fine, but i would not recommend it.

the correct way is to, check your code for extra listeners, remove the listener or change the port number on which you are listening, this fixed my problem.


I was having this till today when I start grunt watch. Finally solved by

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

The annoying message is gone.


You said you are using process.on('uncaughtException', callback);
Where are you executing this statement? Is it within the callback passed to http.createServer?
If yes, different copy of the same callback will get attached to the uncaughtException event upon each new request, because the function (req, res) { ... } gets executed everytime a new request comes in and so will the statement process.on('uncaughtException', callback);
Note that the process object is global to all your requests and adding listeners to its event everytime a new request comes in will not make any sense. You might not want such kind of behaviour.
In case you want to attach a new listener for each new request, you should remove all previous listeners attached to the event as they no longer would be required using:
process.removeAllListeners('uncaughtException');


Our team's fix for this was removing a registry path from our .npmrc. We had two path aliases in the rc file, and one was pointing to an Artifactory instance that had been deprecated.

The error had nothing to do with our App's actual code but everything to do with our development environment.


You need to clear all listeners before creating new ones using:

Client / Server

socket.removeAllListeners(); 

Assuming socket is your client socket / or created server socket.

You can also subscribe from specific event listeners like for example removing the connect listener like this:

this.socket.removeAllListeners("connect");

Node Version : v11.10.1

Warning message from stack trace :

process.on('warning', e => console.warn(e.stack));
(node:17905) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:255:17)
    at Connection.addListener (events.js:271:10)
    at Connection.Readable.on (_stream_readable.js:826:35)
    at Connection.once (events.js:300:8)
    at Connection._send (/var/www/html/fleet-node-api/node_modules/http2/lib/protocol/connection.js:355:10)
    at processImmediate (timers.js:637:19)
    at process.topLevelDomainCallback (domain.js:126:23)

After searching for github issues, documentation and creating similar event emitter memory leaks, this issue was observed due to node-apn module used for iOS push notification.

This resolved it :

You should only create one Provider per-process for each certificate/key pair you have. You do not need to create a new Provider for each notification. If you are only sending notifications to one app then there is no need for more than one Provider.

If you are constantly creating Provider instances in your app, make sure to call Provider.shutdown() when you are done with each provider to release its resources and memory.

I was creating provider object each time the notification was sent and expected the gc to clear it.


Put this in the first line of your server.js (or whatever contains your main Node.js app):

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

and the error goes away :)

참고URL : https://stackoverflow.com/questions/9768444/possible-eventemitter-memory-leak-detected

반응형