fix: 修复 Windows 平台下信号处理器注册问题,避免不必要的注册尝试

This commit is contained in:
DrSmoothl
2026-03-15 16:27:50 +08:00
parent ef11a5fceb
commit e1b3cf6e9f
2 changed files with 41 additions and 9 deletions

View File

@@ -534,6 +534,22 @@ class TestSDK:
class TestPluginSdkUsage:
"""验证仓库内插件按新 SDK 归一化返回值工作。"""
def test_runner_skips_signal_handler_registration_on_windows(self, monkeypatch):
"""Windows 下不应尝试注册 add_signal_handler。"""
from src.plugin_runtime.runner import runner_main
registered_signals = []
class DummyLoop:
def add_signal_handler(self, sig, callback):
registered_signals.append((sig, callback))
monkeypatch.setattr(runner_main.sys, "platform", "win32")
runner_main._install_shutdown_signal_handlers(lambda: None, DummyLoop())
assert not registered_signals
@pytest.mark.asyncio
async def test_builtin_emoji_plugin_handles_normalized_results(self):
from maibot_sdk.context import PluginContext

View File

@@ -9,7 +9,7 @@
6. 转发插件的能力调用到 Host
"""
from typing import Any, List, Optional, Protocol, cast
from typing import Any, Callable, List, Optional, Protocol, cast
from pathlib import Path
@@ -47,6 +47,29 @@ class _ContextAwarePlugin(Protocol):
def _set_context(self, context: Any) -> None: ...
def _install_shutdown_signal_handlers(
mark_runner_shutting_down: Callable[[], None],
loop: Optional[asyncio.AbstractEventLoop] = None,
) -> None:
"""为 Runner 注册关停信号处理器。
Windows 默认事件循环不支持 add_signal_handler且当前 Runner 在 Windows
下由 Host 直接 terminate/kill不依赖进程内信号回调进行优雅收尾。
"""
if sys.platform == "win32":
return
target_loop = loop or asyncio.get_running_loop()
for sig in (signal.SIGTERM, signal.SIGINT):
try:
target_loop.add_signal_handler(sig, mark_runner_shutting_down)
except Exception as exc:
if not isinstance(exc, (NotImplementedError, RuntimeError)):
raise
logger.debug(f"当前事件循环不支持注册 Runner 信号处理器: {exc}")
return
def _disable_runner_console_logging() -> None:
"""关闭 Runner 的控制台日志输出,避免被 Host 从 stderr 二次包装。"""
root_logger = stdlib_logging.getLogger()
@@ -666,14 +689,7 @@ async def _async_main() -> None:
def _mark_runner_shutting_down() -> None:
runner._shutting_down = True
loop = asyncio.get_event_loop()
for sig in (signal.SIGTERM, signal.SIGINT):
try:
loop.add_signal_handler(sig, _mark_runner_shutting_down)
except NotImplementedError:
logger.warning(f"当前平台/事件循环不支持 signal handler跳过注册信号 {sig!s}")
except RuntimeError as exc:
logger.warning(f"注册信号处理器失败,跳过信号 {sig!s}: {exc}")
_install_shutdown_signal_handlers(_mark_runner_shutting_down)
await runner.run()