mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 23:47:54 +08:00
runtime/mcp: spawn servers in their own process group
A terminal Ctrl+C is delivered to every process in the foreground process group, so a server spawned in our group died on any Ctrl+C during a turn - killing in-flight tool calls and leaving the connection dead until /mcp reconnect. start_new_session (POSIX) / CREATE_NEW_PROCESS_GROUP (Windows) puts each server in its own session/group instead. Tests assert the spawned server's process group and session differ from the CLI's (they used to be the same group).
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -97,6 +98,26 @@ async def test_close_terminates_subprocess() -> None:
|
||||
assert proc.returncode is not None
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform == "win32", reason="POSIX process groups only")
|
||||
async def test_server_spawned_outside_our_process_group() -> None:
|
||||
"""Regression: a terminal Ctrl+C must not reach the MCP server.
|
||||
|
||||
The tty delivers SIGINT to every process in the foreground process group, so
|
||||
a server spawned in *our* group died on any Ctrl+C during a turn (killing
|
||||
in-flight tool calls and leaving the connection dead). ``start_new_session``
|
||||
moves the server into its own session/group.
|
||||
"""
|
||||
connection = McpServerConnection("fake", _server_config())
|
||||
await connection.start()
|
||||
try:
|
||||
proc = connection._proc
|
||||
assert proc is not None
|
||||
assert os.getpgid(proc.pid) != os.getpgid(0)
|
||||
assert os.getsid(proc.pid) != os.getsid(0)
|
||||
finally:
|
||||
await connection.aclose()
|
||||
|
||||
|
||||
async def test_manager_start_status_and_call() -> None:
|
||||
manager = McpManager(McpConfig(servers={"fake": _server_config()}, disable=[]))
|
||||
await manager.ensure_started()
|
||||
|
||||
Reference in New Issue
Block a user