aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2017-05-20 14:29:33 -0400
committerRapptz <[email protected]>2017-05-20 14:29:33 -0400
commit9e24d43c635d2454c476a59b9fdaeee2e9014a09 (patch)
treebcd86f48bf3844ecb2f886ba309328e582ecb4a8
parentRe-raise exceptions from Client.start in Client.run. (diff)
downloaddiscord.py-9e24d43c635d2454c476a59b9fdaeee2e9014a09.tar.xz
discord.py-9e24d43c635d2454c476a59b9fdaeee2e9014a09.zip
Rewrite Client.run yet again.
This time it should definitely fix #545.
-rw-r--r--discord/client.py48
1 files changed, 32 insertions, 16 deletions
diff --git a/discord/client.py b/discord/client.py
index 50cff0ee..6c3422f4 100644
--- a/discord/client.py
+++ b/discord/client.py
@@ -452,31 +452,46 @@ class Client:
yield from self.login(*args, bot=bot)
yield from self.connect(reconnect=reconnect)
-
def _do_cleanup(self):
+ log.info('Cleaning up event loop.')
loop = self.loop
if loop.is_closed():
return # we're already cleaning up
- if loop.is_running():
- loop.stop()
+ task = compat.create_task(self.close(), loop=loop)
- loop.run_until_complete(self.close())
- pending = asyncio.Task.all_tasks(loop=loop)
- if pending:
- log.info('Cleaning up after %s tasks', len(pending))
- gathered = asyncio.gather(*pending, loop=loop)
+ def _silence_gathered(fut):
try:
- gathered.cancel()
- loop.run_until_complete(gathered)
-
- # we want to retrieve any exceptions to make sure that
- # they don't nag us about it being un-retrieved.
- gathered.exception()
+ fut.result()
except:
pass
+ finally:
+ loop.stop()
+
+ def when_future_is_done(fut):
+ pending = asyncio.Task.all_tasks(loop=loop)
+ if pending:
+ log.info('Cleaning up after %s tasks', len(pending))
+ gathered = asyncio.gather(*pending, loop=loop)
+ gathered.cancel()
+ gathered.add_done_callback(_silence_gathered)
+ else:
+ loop.stop()
+
+ task.add_done_callback(when_future_is_done)
+ if not loop.is_running():
+ loop.run_forever()
+ else:
+ # on Linux, we're still running because we got triggered via
+ # the signal handler rather than the natural KeyboardInterrupt
+ # Since that's the case, we're going to return control after
+ # registering the task for the event loop to handle later
+ return None
- loop.close()
+ try:
+ return task.result() # suppress unused task warning
+ except:
+ return None
def run(self, *args, **kwargs):
"""A blocking call that abstracts away the `event loop`_
@@ -524,7 +539,8 @@ class Client:
if is_windows:
self._do_cleanup()
- if task.cancelled():
+ loop.close()
+ if task.cancelled() or not task.done():
return None
return task.result()