diff --git a/discord_glhf/bot.py b/discord_glhf/bot.py index 45c6b7f..2bb7c07 100644 --- a/discord_glhf/bot.py +++ b/discord_glhf/bot.py @@ -186,11 +186,15 @@ class DiscordBot: web_port = int(os.getenv('WEB_PORT', '8080')) config = Config() config.bind = [f"0.0.0.0:{web_port}"] + # Allow signals to propagate to main process + config.use_reloader = False + config.shutdown_timeout = 3.0 self.web_app = init_app(self.event_handler) - # Start web interface in background task + # Start web interface in background task with signal handling disabled loop = asyncio.get_event_loop() - loop.create_task(serve(self.web_app, config)) + web_task = loop.create_task(serve(self.web_app, config)) + web_task.set_name('hypercorn_web') # Name task for identification during shutdown logger.info(f"Web interface starting at http://localhost:{web_port}") # Start API manager @@ -279,8 +283,9 @@ class DiscordBot: raise async def stop(self) -> None: - """Stop the bot.""" + """Stop the bot and set running flag to False.""" logger.info("Initiating shutdown...") + self._running = False try: async with self._init_lock: @@ -333,6 +338,7 @@ async def shutdown( ) -> None: """Handle shutdown signals.""" logger.info(f"Received {signal_name}") + try: # Set a flag to prevent new tasks from starting bot.queue_manager.set_shutting_down() @@ -372,11 +378,14 @@ def run_bot(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - # Set up signal handlers - for sig in (signal.SIGTERM, signal.SIGINT): - loop.add_signal_handler( - sig, lambda s=sig: asyncio.create_task(shutdown(s.name, bot, loop)) - ) + # Set up signal handler for SIGTERM only + loop.add_signal_handler( + signal.SIGTERM, + lambda: asyncio.create_task(shutdown('SIGTERM', bot, loop)) + ) + + # Restore default SIGINT handler + signal.signal(signal.SIGINT, signal.default_int_handler) try: loop.run_until_complete(bot.start(token))