mirror of
https://github.com/morluto/rea.git
synced 2026-11-14 18:52:48 +00:00
fix(mcp-doctor): stop the owned process family on every exit path
runProductionMcpDoctor wrapped the SDK StdioClientTransport and only joined its close calls. That transport clears its direct-child reference, ends stdin and signals only that child, so a server whose launcher exited after forking an inherited-stdio descendant left the descendant running while the doctor reported nothing but the transport deadline. Run the doctor on OwnedMcpStdioTransport, which spawns the child in a dedicated POSIX process group or Windows job and verifies group and token-owned descendant cleanup before close returns. Feed stderr through a sink on acquisition so diagnostics survive an early child exit and still honor the 64 KiB retained prefix and full byte count. Covered by a fixture that forks a descendant, exits, and is timed out: the regression asserts the descendant is gone after the doctor returns.
This commit is contained in:
1 parent
3f7d0d2d21
commit
d427fc05c3
4 files changed
+88
-17
No files matched your search
@@ -8,6 +8,7 @@ import { randomUUID } from "node:crypto";
|
||||
import { finished } from "node:stream/promises";
|
||||
import type {
|
||||
OwnedProviderProcessSpawnOptions,
|
||||
ProcessDiagnosticBudget,
|
||||
SpawnedOwnedProviderProcess,
|
||||
} from "./ProviderProcess.js";
|
||||
import type { AnalysisCapturedOutput } from "../domain/analysisErrorBase.js";
|
||||
@@ -62,7 +63,9 @@ export class OwnedMcpStdioTransport implements Transport {
|
||||
readonly maxFrameBytes: number;
|
||||
readonly maxOperationBytes: number;
|
||||
readonly gracefulInputCloseMs?: number;
|
||||
readonly maxDiagnosticBytes?: number;
|
||||
readonly maxDiagnosticBytes?: ProcessDiagnosticBudget;
|
||||
/** Observe the owned child's stderr from acquisition onward, including when it closes early. */
|
||||
readonly onStderr?: (chunk: unknown) => void;
|
||||
readonly notifyOnExit?: boolean;
|
||||
},
|
||||
readonly launcher: OwnedMcpLauncher = spawnOwnedProviderProcess,
|
||||
@@ -113,6 +116,8 @@ export class OwnedMcpStdioTransport implements Transport {
|
||||
spawned.process.stdout.on("data", this.#read);
|
||||
spawned.process.stdout.on("error", this.#error);
|
||||
spawned.process.stderr?.on("data", this.#countStderr);
|
||||
if (this.settings.onStderr !== undefined)
|
||||
spawned.process.stderr?.on("data", this.settings.onStderr);
|
||||
spawned.process.on("error", this.#error);
|
||||
spawned.process.once("exit", this.#exit);
|
||||
spawned.process.once("close", this.#outputClosed);
|
||||
@@ -194,6 +199,8 @@ export class OwnedMcpStdioTransport implements Transport {
|
||||
process?.stdout?.off("data", this.#read);
|
||||
process?.stdout?.off("error", this.#error);
|
||||
process?.stderr?.off("data", this.#countStderr);
|
||||
if (this.settings.onStderr !== undefined)
|
||||
process?.stderr?.off("data", this.settings.onStderr);
|
||||
process?.off("error", this.#error);
|
||||
process?.off("exit", this.#exit);
|
||||
process?.off("close", this.#outputClosed);
|
||||
|
||||
Reference in new issue
Block a user