Ensure Client.close() has finished in __aexit__

This wraps the closing behavior in a task. Subsequent callers of
.close() now await that same close finishing rather than short
circuiting. This prevents a user-called close outside of __aexit__ from
not finishing before no longer having a running event loop.
This commit is contained in:
Michael H
2024-05-04 23:20:36 -04:00
committed by GitHub
parent 8fd1fd805a
commit 88f62d85d2
2 changed files with 31 additions and 23 deletions

View File

@ -481,18 +481,21 @@ class AutoShardedClient(Client):
Closes the connection to Discord.
"""
if self.is_closed():
return
if self._closing_task:
return await self._closing_task
self._closed = True
await self._connection.close()
async def _close():
await self._connection.close()
to_close = [asyncio.ensure_future(shard.close(), loop=self.loop) for shard in self.__shards.values()]
if to_close:
await asyncio.wait(to_close)
to_close = [asyncio.ensure_future(shard.close(), loop=self.loop) for shard in self.__shards.values()]
if to_close:
await asyncio.wait(to_close)
await self.http.close()
self.__queue.put_nowait(EventItem(EventType.clean_close, None, None))
await self.http.close()
self.__queue.put_nowait(EventItem(EventType.clean_close, None, None))
self._closing_task = asyncio.create_task(_close())
await self._closing_task
async def change_presence(
self,