Rapptz / discord.py

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

AutoShardedClient.run() does not return after AutoShardedClient.close() is called #5180

Closed NotMaxee closed 4 years ago

NotMaxee commented 4 years ago

Summary

When using AutoShardedClient (and by inheritance AutoShardedBot) manually closing the client using AutoShardedClient.close() closes the connection to Discord, but never actually causes AutoShardedClient.run() to return, preventing the program from terminating.

This is caused by an issue in shard.py inside AutoShardedClient.connect() (shard.py, line 401) where the while-loop never actually terminates due to no more events being added to the internal queue, causing it to forever wait on the next item.

When AutoShardedClient.close() is called, and all shards are closed, no further events are added to AutoShardedClient.__queue, causing the loop to wait indefinitely for the next item from the queue.

A possible solution that I have found, although I don't know how good it is, is to add the following code to the end of the current AutoShardedClient.close() method, after the call to await self.http.close():

self.__queue.put(EventItem(None, None, None))

The event item is received from the queue, its type does not match any of EventType and thus directly leads into the next iteration of the loop, where the check in while not self.is_closed() causes the loop to exit, and AutoShardedBot.connect() to return.

Reproduction Steps

The following code is enough to reproduce the bug:

import discord

token = "YOUR TOKEN GOES HERE"
client = discord.AutoShardedClient()

@client.event
async def on_ready():
    print("calling client.close()")
    await client.close()
    print("client.close() was called")

print("calling client.run()")
client.run(token)
print("this is never printed")

This prints the following, showcasing that the final print() after client.run(token) is never called.

calling client.run()
calling client.close()
client.close() was called

Expected Results

AutoShardedClient.run() should return after a successful call to AutoShardedClient.close().

Actual Results

AutoShardedClient.run() blocks indefinitely, causing the program to never finish.

Checklist

System Information

Rapptz commented 4 years ago

Thanks this should be fixed now.