fix: graceful SIGTERM shutdown for IRC and Mumble bots
Send IRC QUIT before closing the socket so the server releases the nick immediately. Wrap readline() in wait_for(timeout=2.0) so the _running check triggers even when the server is quiet. Explicitly stop pymumble in the signal handler to accelerate Mumble teardown. Together these eliminate the 10s podman grace-period SIGKILL.
This commit is contained in:
@@ -253,7 +253,10 @@ class Bot:
|
||||
async def _loop(self) -> None:
|
||||
"""Read and dispatch messages until disconnect."""
|
||||
while self._running:
|
||||
line = await self.conn.readline()
|
||||
try:
|
||||
line = await asyncio.wait_for(self.conn.readline(), timeout=2.0)
|
||||
except asyncio.TimeoutError:
|
||||
continue
|
||||
if line is None:
|
||||
log.warning("server closed connection")
|
||||
return
|
||||
|
||||
@@ -10,6 +10,7 @@ import sys
|
||||
from derp import __version__
|
||||
from derp.bot import Bot
|
||||
from derp.config import build_server_configs, resolve_config
|
||||
from derp.irc import format_msg
|
||||
from derp.log import JsonFormatter
|
||||
from derp.plugin import PluginRegistry
|
||||
|
||||
@@ -72,12 +73,24 @@ def _run(bots: list) -> None:
|
||||
|
||||
|
||||
def _shutdown(bots: list) -> None:
|
||||
"""Signal handler: stop all bot loops so cProfile can flush."""
|
||||
"""Signal handler: stop all bot loops and tear down connections."""
|
||||
logging.getLogger("derp").info("SIGTERM received, shutting down")
|
||||
loop = asyncio.get_running_loop()
|
||||
for bot in bots:
|
||||
bot._running = False
|
||||
if hasattr(bot, "conn"):
|
||||
asyncio.get_running_loop().create_task(bot.conn.close())
|
||||
if hasattr(bot, "conn") and bot.conn.connected:
|
||||
loop.create_task(_quit_and_close(bot))
|
||||
elif hasattr(bot, "_mumble") and bot._mumble:
|
||||
bot._mumble.stop()
|
||||
|
||||
|
||||
async def _quit_and_close(bot) -> None:
|
||||
"""Send IRC QUIT and close the connection."""
|
||||
try:
|
||||
await bot.conn.send(format_msg("QUIT", "shutting down"))
|
||||
except Exception:
|
||||
pass
|
||||
await bot.conn.close()
|
||||
|
||||
|
||||
def _dump_tracemalloc(log: logging.Logger, path: str, limit: int = 25) -> None:
|
||||
|
||||
Reference in New Issue
Block a user