检测到可能的EventEmitter内存泄漏

Riz*_*Riz 202 memory-leaks node.js 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)
Run Code Online (Sandbox Code Playgroud)

我在server.js中编写了这样的代码:

http.createServer(
    function (req, res) { ... }).listen(3013);
Run Code Online (Sandbox Code Playgroud)

如何解决这个问题?

vol*_*evo 173

我想在此指出,警告是有原因的,并且很有可能正确的修复不会增加限制,但要弄清楚为什么要为同一事件添加这么多的监听器.如果您知道为什么要添加这么多听众并且确信这是您真正想要的,那么只能增加限制.

我发现这个页面是因为我收到了这个警告,在我的情况下,我使用的一些代码中存在一个错误,即将全局对象转换为EventEmitter!我当然建议不要在全球范围内增加限制,因为你不希望这些事情被忽视.

  • +1.同意.警告表明潜在的泄漏状态,并且无意识地增加maxListeners不一定能解决问题.http://www.jongleberry.com/understanding-possible-eventemitter-leaks.html (11认同)
  • 仅供参考,第一条评论的链接 (jongleberry.com) 已离线。这是存档版本:http://web.archive.org/web/20180315203155/http://www.jongleberry.com/understand-possible-eventemitter-leaks.html (7认同)
  • 它可能是合法代码,例如多个“异步”函数并行运行 (4认同)
  • 如何调试“警告:检测到可能的EventEmitter内存泄漏。添加了11个错误侦听器。使用generator.setMaxListeners()增加限制”。我们应该寻找什么? (2认同)
  • 但是没有堆栈跟踪,并且该错误消息的任何地方都没有代码。我在“警告”和“可能”上有大写的“ W”和“ P”,所以我认为这可能是一个不同的错误。我需要侦听一个以上的事件,但是在任何情况下我都只会调用一次.on,因此不确定问题出在哪里。 (2认同)
  • @ Phil_1984_你找到了解决方案吗?如果不是这似乎工作 - /sf/ask/2693755641/ (2认同)

Cor*_*son 90

这在手册中有解释:http://nodejs.org/docs/latest/api/events.html#events_emitter_setmaxlisteners_n

这是什么版本的Node?您还有其他什么代码?这不是正常行为.

简而言之,它: process.setMaxListeners(0);

另见:node.js - request - 如何"emitter.setMaxListeners()"?

  • `process.setMaxListeners(0); // OMG,它如此简单......:D` (9认同)
  • 这个答案是如何获得所有这些投票的,并被选为正确答案?即使它可以工作,但这是完全错误的! (6认同)
  • 我正在使用`process.on('uncaughtException',callback);` (5认同)
  • 我不会删除最大侦听器限制.你不会得到警告,但你会得到内存泄漏. (5认同)
  • 使用 process.setMaxListeners(0) 可能会在不知不觉中泄漏内存。 (5认同)
  • 这是最糟糕的答案:警告的存在是有原因的;删除它并不能解决任何问题。 (2认同)

zag*_*art 75

默认情况下,任何单个事件最多可以注册10个侦听器.

如果是您的代码,您可以通过以下方式指定maxListeners:

const emitter = new EventEmitter()
emitter.setMaxListeners(100)
// or 0 to turn off the limit
emitter.setMaxListeners(0)
Run Code Online (Sandbox Code Playgroud)

但如果它不是您的代码,您可以使用该技巧来全局增加默认限制:

require('events').EventEmitter.prototype._maxListeners = 100;
Run Code Online (Sandbox Code Playgroud)

当然你可以关掉限制但要小心:

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

BTW.代码应该在应用程序的最开头.

ADD:从节点0.11开始,此代码也可以更改默认限制:

require('events').EventEmitter.defaultMaxListeners = 0
Run Code Online (Sandbox Code Playgroud)

  • 这是在Node 5.6.0中为我工作的唯一解决方案.万分感谢! (5认同)

RLa*_*aaa 62

接受的答案提供了关于如何增加限制的语义,但正如@voltrevo指出警告是有原因的,而你的代码可能有一个bug.

考虑以下错误代码:

//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');
}
Run Code Online (Sandbox Code Playgroud)

现在观察添加监听器的正确方法:

//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');
}
Run Code Online (Sandbox Code Playgroud)

在更改maxListeners之前在代码中搜索类似的问题(在其他答案中有解释)

  • 这个答案应该被接受,因为它显示了警告背后的实际原因以及如何解决它,+ 1 (10认同)
  • 它可能是合法代码,例如多个“异步”函数并行运行 (3认同)

Dav*_*lin 22

替换.on()once().once()当事件由同一函数处理时,使用删除事件侦听器.资料来源:http://nodeguide.com/beginner.html#using-eventemitters

如果这不能解决问题,请在package.json"restler"中重新安装restler:"git://github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d"

这与restler 0.10与节点行为不当有关.你可以看到这个问题在git上关闭了:https://github.com/danwrong/restler/issues/112 但是,npm还没有更新这个,所以这就是你必须引用git头的原因.


小智 6

节点版本:v11.10.1

来自堆栈跟踪的警告消息:

process.on('warning', e => console.warn(e.stack));
Run Code Online (Sandbox Code Playgroud)
(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)

Run Code Online (Sandbox Code Playgroud)

在搜索 github 问题、文档并创建类似的事件发射器内存泄漏后,由于用于 iOS 推送通知的node-apn模块而观察到此问题。

这解决了它:

您应该为您拥有的每个证书/密钥对为每个进程创建一个提供程序。您不需要为每个通知创建一个新的 Provider。如果您只向一个应用程序发送通知,则不需要多个提供程序。

如果您不断在应用中创建 Provider 实例,请确保在完成每个 Provider 后调用 Provider.shutdown() 以释放其资源和内存。

每次发送通知时我都在创建提供者对象,并希望 gc 清除它。


Leg*_*oom 5

在我的 mac osx 上安装 aglio 时,我也收到此警告。

我用cmd修复它。

sudo npm install -g npm@next
Run Code Online (Sandbox Code Playgroud)

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