| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- """
- 操作系统信号和 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}")
|