NodeJS : How to debug “EventEmitter memory leak detected. 11 listeners added”

前端 未结 8 499
攒了一身酷
攒了一身酷 2020-11-28 20:23

How can I debug my application which throw this error:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxList         


        
相关标签:
8条回答
  • 2020-11-28 20:55

    I tried to prototype the EventEmitter for adding log messages into addListener but i could not get it working

    To hook addListener you can do something like this:

    // 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);
    }
    
    0 讨论(0)
  • 2020-11-28 20:56

    I was seeing this when I was running my unit tests. My unit tests were repeatedly calling code that was calling:

    process.on("uncaughtException", () => { ... });
    

    I had to use dependency injection to inject a fake process object, which solved the problem.

    main.js:

    export function main(myProcess) {
        myProcess.on("uncaughtException", () => { ... });
    }
    
    if (require.main === module) { // to prevent this from executing when running unit tests
        main(process);
    }
    

    My unit tests would do:

    const fakeProcess = jasmine.createSpy("process", ["on"]);
    main(fakeProcess);
    
    0 讨论(0)
  • 2020-11-28 20:57

    I ran into the same problem when testing React components using mocha and enzyme.

    I was able to solve my problem by explicitly unmounting components after I had finished testing them.

    The issue was that I was mounting components multiple times in my tests, which were then adding more listeners, until the number of listeners got to 11, and I got a warning.

    I changed my test code by adding the rendered.unmount() line. This fixed the problem for me.

    describe('<CircleArc />', () => {
    
        it('renders', function () {
            const rendered = mount(<CircleArc />);
            assert.ok(rendered.find('path'));
            rendered.unmount();
        });
    }
    
    0 讨论(0)
  • 2020-11-28 21:05

    It turns out that this is a bug in nodejs core, we are talking about this problem here : https://github.com/joyent/node/issues/5108

    Solution for bugged http servers thats throw an EventEmitter memory leak detected and fill up the available memory / available CPU times :

    Revert to legacy version v0.8.23. (You can download and install/compile it from here : http://blog.nodejs.org/2013/04/08/node-v0-8-23-legacy/)

    UPDATE 2018 : I see several feedbacks on this topic whereas the problem looks to be gone since years. Note that this response is only for a leaking http server build with nodejs. If you are in other scenario, please look the others responses on this thread and dont downgrade your version (as suggested on this response), you will waste your time.

    0 讨论(0)
  • 2020-11-28 21:06

    For me it's looks like your event loop is blocked. This can happen if you are doing cpu intensive tasks in node.js event loop. You can use child process to do intensive task.

    You can check what is blocking node.js using following methods:

    1. Measure computation time of each call. Log if time is high so you know app is misbehaving.
    2. Set up a log schedule so you know when something blocking loop
      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);
    3. Use profile.
    4. Use this for logging and profiling. It's library used in Nodejitsu.
    0 讨论(0)
  • 2020-11-28 21:06

    This is exactly what happened to me. For me, I nested an event listener within another event listener accidentally.

    Look at your code and make sure you DO NOT have an event listener block WITHIN another event listener block for example(unless you are doing it on purpose):

    socket.on('data', function(data) {
    //code goes here
    
    socket.on('close' , function() {
    //code goes here
         });
    
       });
    

    In the wrong example above, the socket.on ('close') listener should be OUTSIDE of the socket.on('data') block.

    In my case when I received 5 data streams, the socket.on('close') listener is waiting for a close event to happen. When I close once, another 4th closing event would execute. This is clearly not what I wanted. This is due to the nature of Node.js which is non-blocking. It 'remembers' events due to the callback function.

    0 讨论(0)
提交回复
热议问题