[Windows Desktop] Terminating a shell command does not kill its descendant process tree

Open 💬 3 comments Opened Jul 13, 2026 by Hadeanyolo
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Codex version

Codex Desktop for Windows: 26.707.8479.0

Platform

Windows 11 x64

What happened?

Codex Desktop started a Git command that created multiple levels of child processes:

Codex / shell wrapper
└── git.exe
    └── git.exe
        ├── git.exe
        └── ssh.exe

The command was terminated through the Codex tool interface, and Codex reported:

Script terminated

However, the descendant processes were not terminated. They continued running and creating additional descendants after Codex reported successful termination.

The number of surviving processes initially reached approximately:

  • 660+ git.exe
  • 660+ ssh.exe

It later exceeded approximately:

  • 1,200 git.exe
  • 1,200 ssh.exe

Closing Codex Desktop did not terminate these processes.

Because surviving descendants continued creating new processes, terminating individual git.exe and ssh.exe processes was ineffective. A complete Windows restart was ultimately required.

System impact

The surviving process tree caused severe resource exhaustion:

  • System committed memory increased to approximately 61.6 / 63.2 GB.
  • The computer has 32 GB of physical RAM.
  • The Windows page file expanded substantially.
  • Free space on the system drive decreased by approximately 13 GB.
  • The Windows graphical interface became unstable.
  • Resource usage returned to normal after restarting Windows.

The memory was primarily consumed by the surviving command descendants rather than by the Codex Desktop process itself.

Expected behavior

When Codex reports that a command has been terminated, the entire process tree created by that command should be terminated, including grandchildren and deeper descendants.

On Windows, shell commands should be placed in a Windows Job Object configured with kill-on-job-close behavior, or managed using an equivalent process-tree termination mechanism.

Codex should not display Script terminated while descendants belonging to the command are still running.

Closing Codex Desktop should also clean up command descendants owned by that Codex session.

Actual behavior

Codex appears to have terminated only the directly tracked process or shell wrapper.

Deeper descendants survived, became detached from the terminated command, and continued running independently.

Triggering command

The incident was triggered by a Git partial-clone command over SSH, equivalent to:

git clone --filter=blob:none --sparse --depth=1 --no-checkout user@example-host:/redacted/repository redacted-local-directory

Git itself entered a recursive child-process condition. That Git behavior is already being addressed upstream and is not the primary subject of this report.

The Codex-specific issue is that terminating the command did not contain or terminate its complete process tree.

Related Codex issue

This appears related to:

https://github.com/openai/codex/issues/4337

That report describes child processes surviving command timeouts. It was closed after a fix, but this incident occurred in a current Windows Desktop build and may indicate that Windows descendant cleanup remains incomplete or has regressed.

Reproducibility

I have not deliberately reproduced the incident because it can create thousands of processes, exhaust system commit capacity, destabilize Windows, and require a restart.

All hostnames, usernames, repository names, SSH aliases, task identifiers, and local paths in this report have been redacted.

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #32462

Powered by Codex Action

Hadeanyolo · 1 month ago
Potential duplicates detected. Please review them and close your issue if it is a duplicate. * Chrome processes not cleaned up after execution on Windows #32462 _Powered by Codex Action_

Thanks for identifying #32462. The two issues appear related, but they do not seem to be exact duplicates.

The main differences are:

  • #32462 affects Codex CLI running through Git Bash/MSYS.
  • #32462 occurs after codex exec completes normally.
  • The surviving descendants in #32462 are Chrome processes and primarily cause high CPU usage.

In this report:

  • The affected surface is Codex Desktop for Windows.
  • The command was explicitly terminated through the Codex tool interface.
  • Codex reported Script terminated, but multiple generations of git.exe and ssh.exe descendants remained alive.
  • The process count grew into the thousands.
  • System committed memory reached approximately 61.6 / 63.2 GB, the page file expanded, and the Windows graphical interface became unstable.
  • Closing Codex Desktop did not clean up the descendants, and a Windows restart was required.

The reports may share an underlying Windows process-tree cleanup problem, but they exercise different lifecycle paths: normal CLI completion versus explicit Desktop tool termination.

I suggest keeping them linked while maintainers determine whether both paths use the same process-management implementation.

dex-tripnull · 5 days ago

Additional reproducible Windows Desktop evidence shows the descendant-cleanup gap can occur after an SSH-backed Git command finishes normally, not only after tool termination.

Environment:

  • Codex Desktop on Windows, managed workspace-write execution
  • Outer shell: exact installed PowerShell 7 executable
  • SSH-backed Git operation against a private GitHub repository

Latest bounded reproduction:

  1. Ran exactly one approved-context git push --porcelain origin HEAD:refs/heads/main.
  2. The Git command exited successfully.
  3. GitHub-side structured verification independently confirmed that the remote head exactly matched the frozen local head.
  4. A newly created ssh.exe descendant (PID 17256, start time 2026-08-22T12:45:45.2295367-04:00) remained alive after the Git parent and shell command had ended.
  5. A later bounded process recheck still reported that exact PID live. No second push or cleanup attempt was made.

This is the fourth independently observed instance in the same environment:

  • one failed push left ssh.exe PID 20488;
  • one successful push left PID 29108;
  • one read-only git ls-remote left PID 26132;
  • the successful approved-context push above left PID 17256.

Earlier exact-PID cleanup attempts using Stop-Process and taskkill were denied, including narrowly elevated attempts. Older or unrelated SSH processes were deliberately left untouched.

Impact:

  • command completion does not imply descendant cleanup;
  • inaccessible SSH children accumulate across ordinary Git publication and read-only remote operations;
  • agents must stop retries and independently reconcile remote state to avoid duplicate pushes.

Expected:

  • every process tree created for a Git/SSH operation is owned and reaped when the command completes, times out, or is cancelled;
  • if cleanup cannot complete, the tool should return an explicit process-lifecycle failure and an owned cleanup handle instead of reporting only the Git command result.

No private repository name, remote URL, key path, credential, or command output is included here.