feat: kill orphaned Chrome processes on GCU server shutdown

This commit is contained in:
bryan
2026-03-12 14:26:05 -07:00
parent 0c900fb50e
commit c37185732a
+35 -1
View File
@@ -21,9 +21,13 @@ Environment Variables:
from __future__ import annotations
import argparse
import atexit
import asyncio
import logging
import os
import sys
from contextlib import asynccontextmanager
from typing import AsyncIterator
logger = logging.getLogger(__name__)
@@ -57,7 +61,37 @@ from fastmcp import FastMCP # noqa: E402
from gcu import register_gcu_tools # noqa: E402
mcp = FastMCP("gcu-tools")
# ---------------------------------------------------------------------------
# Shutdown hooks — kill Chrome processes when the server exits
# ---------------------------------------------------------------------------
@asynccontextmanager
async def _lifespan(server: FastMCP) -> AsyncIterator[dict]:
"""FastMCP lifespan hook: clean up all browsers on shutdown."""
yield {}
from gcu.browser.session import shutdown_all_browsers
logger.info("Server shutting down, cleaning up browser sessions...")
await shutdown_all_browsers()
def _sync_shutdown() -> None:
"""atexit fallback: run async browser cleanup from sync context.
Covers SIGTERM and other exits where the lifespan teardown may not run.
"""
from gcu.browser.session import shutdown_all_browsers
try:
asyncio.run(shutdown_all_browsers())
except Exception:
pass
atexit.register(_sync_shutdown)
mcp = FastMCP("gcu-tools", lifespan=_lifespan)
def main() -> None: