[Windows][MCP] taskkill /T can terminate the host application after stale PPID reuse
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- rust
- Domain
- cli, operating-systems
Research direction
Start in codex-rs/rmcp-client/src/stdio_server_launcher.rs and compare its Windows cleanup with the Job Object abstraction in codex-rs/utils/pty/src/win/job.rs. Run the existing Windows tests and add a regression test modeling stale PPID reuse and cycles. Done means MCP cleanup cannot reach Codex, ancestors, siblings, or unrelated processes, and ownership is based on process or Job handles rather than PID-tree traversal.
Written by the indexing model from the issue text.
Description
What issue are you seeing?
Codex 0.145.0 forcibly terminated a long-running third-party Windows desktop host, its WebView processes, and other concurrent agents while tearing down a local stdio MCP server.
This is a process-ownership correctness issue, not only a process leak or taskkill.exe performance issue.
On Windows, LocalProcessTerminator stores only a numeric PID:
Cleanup then invokes taskkill /PID <pid> /T /F, suppresses stdout/stderr, and ignores the result:
taskkill /T reconstructs descendants from numeric PID/PPID relationships. A Windows parent PID is not a durable process identity: after the original parent exits, the child retains the numeric parent ID, and that number can later be reused by an unrelated process. A stale parent edge can therefore create a cycle in the numerical process graph. Tree cleanup from a descendant may then include the long-running host and all of its other children.
The live descendant chain immediately before this incident was reconstructed from Sysmon process-creation events:
DrawCode.exe 38700
-> cmd.exe 47976
-> node.exe 61580
-> node.exe 37348
-> codex.exe 48284
-> codeg-mcp.exe 58508
The host had been started by a short-lived installer process and had remained alive for approximately 23 hours and 45 minutes. Its original process-creation event had already rotated out of the event log, so the exact stale PPID can no longer be recovered.
Observed timeline (UTC):
| Time | Event |
|---|---|
02:20:31.221 |
Delegated Codex work completed normally. |
02:20:31.240 |
codex.exe PID 48284 started taskkill /PID 58508 /T /F. |
02:20:31.269 |
Multiple MCP/Codex helper processes began terminating. |
02:20:31.272 |
Another Codex process started taskkill /PID 22304 /T /F. |
02:20:31.330 |
Codex PID 48284 started taskkill /PID 38232 /T /F. |
02:20:31.362 |
The host process, PID 38700, terminated with exit code 1. |
Approximately 90 processes terminated in the two-second incident window, including MCP companions, Codex processes, other agent processes, and WebView processes. Two taskkill.exe instances themselves terminated with 0xC000010A (STATUS_PROCESS_IS_TERMINATING). There was no matching Application Error, Windows Error Reporting event, crash dump, panic, fatal log, or normal host shutdown record.
Because three taskkill calls overlapped, the retained logs cannot identify which invocation issued the final TerminateProcess against the host, or whether the stale edge involved PID 58508, 22304, or 38232. The first broad termination cascade began immediately after the PID 58508 cleanup. This limitation does not change the unsafe primitive: /T is traversing recyclable numeric parent relationships without process-creation identity validation.
What steps can reproduce the bug?
The trigger is timing-dependent because it requires PID reuse:
- Start a long-running Windows host that launches Codex and local stdio MCP servers. Launch the host from a short-lived installer or helper process.
- Allow the original parent to exit while the host remains alive.
- Keep the host running under normal process churn until the stale parent PID is reused by an MCP server process or another process in its cleanup graph.
- Complete or disconnect an MCP-backed Codex session.
- Codex runs
taskkill /PID <mcp-pid> /T /F. - If the reused PID closes a numerical parent cycle, the host and its unrelated child trees are forcibly terminated.
A regression test does not need to wait for natural PID reuse. It can model a process snapshot containing a stale edge where the alleged child was created before the current process holding the parent PID. Cleanup must reject that edge, detect cycles, and never include the Codex process or its ancestors.
What is the expected behavior?
Terminating a local stdio MCP server must only affect the process tree that Codex created and owns. It must never terminate the Codex host, Codex itself, sibling agents, sibling MCP servers, or UI processes. PID reuse must not change cleanup ownership.
Additional information
Environment:
- Windows 11 Pro, version
10.0.26200, x64 - Codex CLI
0.145.0 - Host: DrawCode
0.21.9-mycodebuddy.1, usingcodex-acpand a per-launch local stdio MCP companion
Suggested fix:
- Replace
taskkill /T /Fwith a per-MCP Windows Job Object configured withJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. - Assign the MCP root process to the Job before it can execute user code, using suspended creation or
PROC_THREAD_ATTRIBUTE_JOB_LIST, then resume it. - Retain Job/process handles as the ownership identity; keep PID only for diagnostics.
- Close MCP stdin and allow a bounded graceful-shutdown period, then call
TerminateJobObjectif necessary. - If Job assignment fails, fall back to terminating only the already-owned direct child handle. Do not fall back to PID-tree traversal.
Codex already has a reusable Job Object abstraction:
Related reports:
- https://github.com/openai/codex/issues/34260 (
taskkill.execleanup storms) - https://github.com/openai/codex/issues/34614 (MCP grandchildren leak; Job Object suggested)
- https://github.com/openai/codex/issues/35782 (whole desktop application termination under concurrent tasks)
Sanitized Sysmon event exports can be provided if needed. Local paths, command arguments containing authentication material, and private task content have been intentionally omitted.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- Avg merge
- 1m
- Merged PRs (30d)
- 1k
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openai/codex
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
bug CLI windows-os
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
macOS sandbox blocks hw.optional.arm64 sysctl, causing Flutter to misdetect Apple Silicon as x64 Openbug CLI sandbox
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug CLI TUI
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
CLI config enhancement skills
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
A-linter
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
oxc-project/oxc#26863 ·