44from __future__ import annotations
55
66import logging
7+ import signal
78from asyncio import (
89 iscoroutinefunction ,
910 ensure_future ,
@@ -201,6 +202,17 @@ def __init__(
201202 throttler : ThrottleInterface = DefaultThrottleHandler ,
202203 reconnect : bool = True ,
203204 ):
205+ def sigint_handler (_signal , _frame ):
206+ _log .info ("SIGINT received, shutting down..." )
207+
208+ # A print statement to make sure the user sees the message
209+ print ("Closing the client loop, this can take a few seconds..." )
210+
211+ create_task (self .http .close ())
212+ if self .loop .is_running ():
213+ self .loop .stop ()
214+
215+ signal .signal (signal .SIGINT , sigint_handler )
204216
205217 if isinstance (intents , Iterable ):
206218 intents = sum (intents )
@@ -218,13 +230,14 @@ def __init__(
218230 APIObject .link (self )
219231
220232 self .throttler = throttler
221- self .event_mgr = EventMgr ()
222233
223234 async def get_gateway ():
224235 return GatewayInfo .from_dict (await self .http .get ("gateway/bot" ))
225236
226- loop = get_event_loop ()
227- self .gateway : GatewayInfo = loop .run_until_complete (get_gateway ())
237+ self .loop = get_event_loop ()
238+ self .event_mgr = EventMgr (self .loop )
239+
240+ self .gateway : GatewayInfo = self .loop .run_until_complete (get_gateway ())
228241
229242 # The guild and channel value is only registered if the Client has the GUILDS
230243 # intent.
@@ -495,9 +508,8 @@ def execute_event(calls: List[Coro], gateway: Gateway, *args, **kwargs):
495508
496509 def run (self ):
497510 """Start the bot."""
498- loop = get_event_loop ()
499- ensure_future (self .start_shard (0 , 1 ), loop = loop )
500- loop .run_forever ()
511+ ensure_future (self .start_shard (0 , 1 ), loop = self .loop )
512+ self .loop .run_forever ()
501513
502514 def run_autosharded (self ):
503515 """
@@ -515,12 +527,10 @@ def run_shards(self, shards: Iterable, num_shards: int):
515527 num_shards: int
516528 The total amount of shards.
517529 """
518- loop = get_event_loop ()
519-
520530 for shard in shards :
521- ensure_future (self .start_shard (shard , num_shards ), loop = loop )
531+ ensure_future (self .start_shard (shard , num_shards ), loop = self . loop )
522532
523- loop .run_forever ()
533+ self . loop .run_forever ()
524534
525535 async def start_shard (self , shard : int , num_shards : int ):
526536 """|coro|
@@ -554,11 +564,33 @@ async def start_shard(self, shard: int, num_shards: int):
554564
555565 create_task (gateway .start_loop ())
556566
557- def __del__ (self ):
558- """Ensure close of the http client."""
567+ @property
568+ def is_closed (self ) -> bool :
569+ """
570+ Returns
571+ -------
572+ bool
573+ Whether the bot is closed.
574+ """
575+ return self .loop .is_running ()
576+
577+ def close (self ):
578+ """
579+ Ensure close of the http client.
580+ Allow for script execution to continue.
581+ """
559582 if hasattr (self , "http" ):
560583 create_task (self .http .close ())
561584
585+ self .loop .stop ()
586+
587+ def __del__ (self ):
588+ if self .loop .is_running ():
589+ self .loop .stop ()
590+
591+ if not self .loop .is_closed ():
592+ self .close ()
593+
562594 async def handle_middleware (
563595 self ,
564596 payload : GatewayDispatch ,
0 commit comments