""" 操作系统信号和 Windows 控制台事件处理。 """ import sys import threading import signal from foundation.observability.logger.loggering import server_logger _shutdown_lock = threading.Lock() _shutdown_called = False def _run_shutdown_once(shutdown_callback): """确保 shutdown 回调在整个进程生命周期内只执行一次。""" global _shutdown_called with _shutdown_lock: if _shutdown_called: return _shutdown_called = True shutdown_callback() def setup_signal_handlers(shutdown_callback): """注册信号处理器,shutdown_callback 会在收到终止信号时调用(通过 _run_shutdown_once 确保只执行一次)。""" def handler(signum, frame): server_logger.info(f"收到信号 {signum},正在停止服务...") _run_shutdown_once(shutdown_callback) try: signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGTERM, handler) except AttributeError: pass if sys.platform == 'win32': _setup_windows_handler(shutdown_callback) def _setup_windows_handler(shutdown_callback): try: import win32api def win32_handler(dwCtrlType): CTRL_C_EVENT = 0 CTRL_BREAK_EVENT = 1 CTRL_CLOSE_EVENT = 2 CTRL_SHUTDOWN_EVENT = 6 if dwCtrlType in (CTRL_C_EVENT, CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT, CTRL_SHUTDOWN_EVENT): server_logger.info(f"收到Windows控制台事件 {dwCtrlType},正在停止服务...") # 将耗时 shutdown 操作放到后台线程,避免阻塞 console handler 超时 threading.Thread( target=lambda: _run_shutdown_once(shutdown_callback), daemon=True, ).start() return False win32api.SetConsoleCtrlHandler(win32_handler, True) except (ImportError, AttributeError) as e: server_logger.debug(f"Windows控制台事件处理不可用: {e}")