discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.36k stars 3.97k forks source link

Possible memory leak when switching voice channels #5589

Closed InfiniteMarcus closed 3 years ago

InfiniteMarcus commented 3 years ago

Please describe the problem you are having in as much detail as possible:

Every time my bot switch between voice channels 4 times (manually dragging and dropping it in Discord interface or moving with JS code using channel.join()) I receive the following warning:

(node:12164) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 closing listeners added to [VoiceConnection]. Use emitter.setMaxListeners() to increase limit

Also, this is the output using --trace-warnings:

(node:14120) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 closing listeners added to [VoiceConnection]. Use emitter.setMaxListeners() to increase limit at _addListener (events.js:390:17) at VoiceConnection.addListener (events.js:406:10) at new VoiceConnectionUDPClient (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\voice\networking\VoiceUDPClient.js:47:26) at VoiceConnection.connect (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\voice\VoiceConnection.js:416:24) at VoiceConnection.reconnect (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\voice\VoiceConnection.js:344:10) at VoiceConnection.setTokenAndEndpoint (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\voice\VoiceConnection.js:234:12) at ClientVoiceManager.onVoiceServer (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\voice\ClientVoiceManager.js:47:32) at Object.module.exports [as VOICE_SERVER_UPDATE] (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\websocket\handlers\VOICE_SERVER_UPDATE.js:5:16) at WebSocketManager.handlePacket (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\websocket\WebSocketManager.js:384:31) at WebSocketShard.onPacket (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\client\websocket\WebSocketShard.js:444:22)

And even if I ignore this warning and try to move the bot more times, this unhandled error appears (I don't believe it is related to this issue, but I think is important to detail because I found with the same tests):

'WebSocket was closed before the connection was established', error: Error: WebSocket was closed before the connection was established at WebSocket.close (C:\Users\super\Desktop\teste issue\node_modules\ws\lib\websocket.js:22 4:14) at VoiceWebSocket.reset (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\cl ient\voice\networking\VoiceWebSocket.js:53:60) at VoiceWebSocket.shutdown (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src \client\voice\networking\VoiceWebSocket.js:44:10) at VoiceConnection.connect (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src \client\voice\VoiceConnection.js:412:42) at VoiceConnection.reconnect (C:\Users\super\Desktop\teste issue\node_modules\discord.js\s rc\client\voice\VoiceConnection.js:344:10) at VoiceConnection.setTokenAndEndpoint (C:\Users\super\Desktop\teste issue\node_modules\di scord.js\src\client\voice\VoiceConnection.js:234:12) at ClientVoiceManager.onVoiceServer (C:\Users\super\Desktop\teste issue\node_modules\disco rd.js\src\client\voice\ClientVoiceManager.js:47:32) at Object.module.exports [as VOICE_SERVER_UPDATE] (C:\Users\super\Desktop\teste issue\node _modules\discord.js\src\client\websocket\handlers\VOICE_SERVER_UPDATE.js:5:16) at WebSocketManager.handlePacket (C:\Users\super\Desktop\teste issue\node_modules\discord. js\src\client\websocket\WebSocketManager.js:384:31) at WebSocketShard.onPacket (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src \client\websocket\WebSocketShard.js:444:22) }) at VoiceConnection.emit (events.js:304:17) at VoiceWebSocket.<anonymous> (C:\Users\super\Desktop\teste issue\node_modules\discord.js\sr c\client\voice\VoiceConnection.js:422:32) at VoiceWebSocket.emit (events.js:315:20) at VoiceWebSocket.onError (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\cl ient\voice\networking\VoiceWebSocket.js:160:10) at WebSocket.onError (C:\Users\super\Desktop\teste issue\node_modules\ws\lib\event-target.js :140:16) at WebSocket.emit (events.js:315:20) at abortHandshake (C:\Users\super\Desktop\teste issue\node_modules\ws\lib\websocket.js:732:1 5) at WebSocket.close (C:\Users\super\Desktop\teste issue\node_modules\ws\lib\websocket.js:224: 14) at VoiceWebSocket.reset (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\clie nt\voice\networking\VoiceWebSocket.js:53:60) at VoiceWebSocket.shutdown (C:\Users\super\Desktop\teste issue\node_modules\discord.js\src\c lient\voice\networking\VoiceWebSocket.js:44:10)

Of course that moving so many times between channels is not a good practice, but this is a quite possible and common reality to see in Discord, mainly because you can found this issue with only drag and drop.

Include a reproducible code sample here, if possible:

I replicated this issue both in a new bot and in a more complex one. This is the last code I tried:

const Discord = require('discord.js');

const client = new Discord.Client();

client.login('token');

client.on('ready', () => {
    console.log("Bot online");
});

client.on('message', msg => {

    if(msg.author.bot) return;

    const channel = msg.member.voice.channel;

    if(channel)
        channel.join();
});

Solutions that I tried (and failed):

    if(warning.name === "MaxListenersExceededWarning"){
        client.voice.connections.each( con => {            
            const l = con.listeners('closing'); 

            if(con.listenerCount('closing') == 11){
                con.removeListener('closing', l[0]);
                con.removeListener('closing', l[1]);
                con.removeListener('closing', l[2]);
                con.removeListener('closing', l[3]);
            }
        });

Further details:

Relevant client options:

iCrawl commented 3 years ago

Yes, this won't cause a memory leak (not to any substantial degree anyway). It's simply a warning message that gets printed in case we don't clean those listeners up, and as such a really unfortunate and misleading warning too.

amishshah commented 3 years ago

Hi there,

We're working on a new implementation of Discord's Voice API that has better playback quality and is more reliable than what we currently support in Discord.js v12 - check it out at https://github.com/discordjs/voice!

The new library solves many of the issues that users are facing, and as part of this, we're dropping built-in support for voice in our next major release. We have a PR (https://github.com/discordjs/discord.js/pull/5402) that adds native support for our new voice library - once this PR is merged, this issue will be closed.

You can still use our new voice library before that PR lands - just take a look at our music bot example to see how to get started upgrading your voice code. By using the boilerplate music player in the example, you can make it even easier to upgrade your code.

Note that the PR above only reduces some of the boilerplate code you'd otherwise have to write - you do not have to wait for the PR to be merged to start using the new voice library.


If you have any questions about this, feel free to: