Rapptz / discord.py

An API wrapper for Discord written in Python.
http://discordpy.rtfd.org/en/latest
MIT License
14.7k stars 3.74k forks source link

Bot voice state desynchronization #2037

Closed JellyWX closed 5 years ago

JellyWX commented 5 years ago

Summary

The bot, on occasion, fails to properly recall it's own voice state, causing it to fail to play audio in the specific guild. I presume this is an issue with caching, but have not attempted to diagnose this

Reproduction Steps

The code I use to connect to voice channels on demand is:

        try:
            voice = await v_c.connect()
        except discord.errors.ClientException:
            voice = [v for v in self.voice_clients if v.channel.guild == v_c.guild][0]
            if voice.channel != v_c:
                await voice.disconnect()
                voice = await v_c.connect()

Along with an auto-disconnect snippet:

        await self.wait_until_ready()
        while not client.is_closed():

            [await vc.disconnect() for vc in self.voice_clients if not vc.is_playing()]
            await asyncio.sleep(180)

The autodisconnect snippet will also fail once the desync starts on the guild

Expected Results

The bot to disconnect after around 3 mins, and reconnect/play audio on command

Actual Results

Bot sits unresponsive in VC until process is restarted. Traceback is as if it's already connected to a VC, but is impossible to disconnect it. This issue occurs very rarely, but does occur; often notice it after the bot has been online for at least a day. Bot is autosharded (2'000+ guilds)

Mar 31 20:32:20 jellywx.com python3[5767]: Task exception was never retrieved
Mar 31 20:32:20 jellywx.com python3[5767]: future: <Task finished coro=<Client._run_event() done, defined at /usr/local/lib/python3.6/dist-packages/discord/client.py:216> exception=ClientException('Already connected to a voice channel.',)>
 Traceback (most recent call last):
   File "/home/jude/soundfx-bot/main.py", line 152, in play_sound
     voice = await v_c.connect()
   File "/usr/local/lib/python3.6/dist-packages/discord/abc.py", line 978, in connect
     raise ClientException('Already connected to a voice channel.')
 discord.errors.ClientException: Already connected to a voice channel.
 During handling of the above exception, another exception occurred:
 Traceback (most recent call last):
   File "/usr/local/lib/python3.6/dist-packages/discord/client.py", line 223, in _run_event
     await self.on_error(event_name, *args, **kwargs)
   File "/usr/local/lib/python3.6/dist-packages/discord/client.py", line 218, in _run_event
     await coro(*args, **kwargs)
   File "/home/jude/soundfx-bot/main.py", line 248, in on_voice_state_update
     await self.play_sound(member.voice.channel, user.join_sound)
   File "/home/jude/soundfx-bot/main.py", line 157, in play_sound
     voice = await v_c.connect()
   File "/usr/local/lib/python3.6/dist-packages/discord/abc.py", line 978, in connect
     raise ClientException('Already connected to a voice channel.')
discord.errors.ClientException: Already connected to a voice channel.

System Information

Harmon758 commented 5 years ago

Have you tried using the force kwarg option for VoiceClient.disconnect? Setting it to True should work and mitigate this issue.

JellyWX commented 5 years ago

I will try that, forgot to check for any extra flags on that method. However I believe there is still an issue here, since the voice client doesn't appear in the all voice clients (so I can't autodisconnect it)

⁣Get BlueMail for Android ​

On 1 Apr 2019, 02:19, at 02:19, Harmon notifications@github.com wrote:

Have you tried using the force kwarg option for VoiceClient.disconnect? Setting it to True should work and mitigate this issue.

-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/Rapptz/discord.py/issues/2037#issuecomment-478405347

MusicOnline commented 5 years ago

Irrelevant to this issue, but Guild.voice_client exists. You don't have to do a list comprehension or utils.get yourself. (A shortcut through Context also exists.)

https://discordpy.readthedocs.io/en/rewrite/api.html#discord.Guild.voice_client

JellyWX commented 5 years ago

These are valid suggestions which I will take on board however neither tackle the actual issue, which occurs during the background loop.

The background loop contains the following:

[await vc.disconnect() for vc in self.voice_clients if not vc.is_playing()]

This is to check all voice connections and disconnect any that are not playing. However, on occasion a voice connection will not be available within the bot's voice_clients attribute, and therefore will not disconnect until the bot closes.

I apologize if I misunderstood either of your comments, but I believe this is still an issue and not just a poor coding choice

Rapptz commented 5 years ago

To fix this issue, the library provides the force=True keyword argument to disconnect as Harmon said.

If this snippet of code does not work then feel free to re-open the issue, but there are already mitigations in the library for when the voice client state is strange.

[await vc.disconnect(force=True) for vc in self.voice_clients if not vc.is_playing()]
JellyWX commented 5 years ago

That snippet doesn't work, since sometimes not all voice clients are available within self.voice_clients, however it's not an issue that is easy to reproduce since it seems to happen randomly

m13253 commented 3 years ago

I can confirm this bug still exists in the latest version.

I use my bot to stream radio 24 hour/day, and this issue happens every two or three days. This is annoying because I will need to log on to my server and restart my bot.

it's not an issue that is easy to reproduce since it seems to happen randomly

Steps to reproduce:

  1. Connect to a voice channel
  2. Keep playing something
  3. Wait for 1-3 days, occasionally you will hear the notification sounds due to bots reconnecting
  4. Approximately 30% the chance each time, the bot will stop producing sound
  5. Due to Murphy's Law, this issue will definitely happen as long as you keep waiting

Symptoms:

  1. Most of the time the bot is still in the voice channel from a user's perspective, (sometimes isn't.)
  2. Most of the time self.voice_clients does not show the affected voice channel, (sometimes does.)
  3. Rejoining to the channel programmatically may randomly result in a “already connected to channel”.
  4. If rejoining succeeds, the same issue may happen again frequently within 1 or 2 hours unless the whole program is restarted.
JellyWX commented 3 years ago

I can confirm this bug still exists in the latest version.

I use my bot to stream radio 24 hour/day, and this issue happens every two or three days. This is annoying because I will need to log on to my server and restart my bot.

it's not an issue that is easy to reproduce since it seems to happen randomly

Steps to reproduce:

1. Connect to a voice channel

2. Keep playing something

3. Wait for 1-3 days, occasionally you will hear the notification sounds due to bots reconnecting

4. Approximately 30% the chance each time, the bot will stop producing sound

5. Due to Murphy's Law, this issue will definitely happen as long as you keep waiting

Symptoms:

1. Most of the time the bot is still in the voice channel from a user's perspective, (sometimes isn't.)

2. Most of the time `self.voice_clients` does not show the affected voice channel, (sometimes does.)

3. Rejoining to the channel programmatically may randomly result in a “already connected to channel”.

4. If rejoining succeeds, the same issue may happen again frequently within 1 or 2 hours unless the whole program is restarted.

You should probably open a new issue regarding this. I have since switched from d.py to serenity