Codex IDE sidebar Git-origin polling triggers severe Windows PID 4 Section-handle growth
Bug: Codex IDE sidebar Git-origin polling triggers severe Windows PID 4 Section-handle growth
Summary
On one Windows workstation, enabling the OpenAI Codex VS Code extension causes
a continuous storm of short-lived git.exe and conhost.exe processes. This
correlates with severe accumulation of unnamed Section handles in Windows PID
4 (System), eventually causing system-wide resource exhaustion.
A controlled uninstall/reinstall test reproduced the problem on two Codex
extension builds. Removing Codex stops both the Git process storm and sustained
PID 4 handle growth. Freshly reinstalling Codex makes both return.
Environment
- Operating system: Windows 11 x64
- VS Code: 1.130.0
- Git for Windows installed
- Original affected Codex extension:
openai.chatgpt@26.721.30844 - Freshly reinstalled Codex extension:
openai.chatgpt@26.721.41059 - Repositories include a relatively large set of historical local/network
workspaces associated with prior Codex threads.
Reproduction and controlled results
Codex installed and active
Before uninstall:
- Repeated Git operations appeared every few seconds.
- Representative commands:
git -c core.hooksPath=NUL -c core.fsmonitor= for-each-ref --count=100 ...git config --null --get core.fsmonitorgit -c core.hooksPath=NUL -c core.fsmonitor= rev-parse --abbrev-ref HEADgit -c core.hooksPath=NUL -c core.fsmonitor= remote- Codex logs identified the repeating request as:
requestKind=git-originssource=sidebar_workspace_task_groups_task_dirs- PID 4 handle growth repeatedly measured approximately 15–22 handles/second.
- One 20-second sample measured +357 handles (17.85 handles/second).
- A three-minute sample observed 474 new Git processes and 360 new conhost
processes.
Disabling VS Code's built-in Git integration did not stop the behavior.
Removing GitLens and a third-party Claude/Codex history extension also did not
stop it.
Codex uninstalled
After removing openai.chatgpt and confirming that no codex.exe process was
running:
- Three consecutive one-minute PID 4 rates were:
- -0.16 handles/second
- -0.54 handles/second
- +2.68 handles/second
- Zero Git processes were observed.
- An extended 15-minute test averaged 1.02 PID 4 handles/second.
- Zero Git processes were observed throughout that 15-minute window.
Fresh Codex reinstall
After installing openai.chatgpt@26.721.41059:
- PID 4 increased by 1,472 handles in 60 seconds: 24.53 handles/second.
- 172 short-lived Git processes were observed in the same minute.
- The Git commands reproduced the same
core.hooksPath=NUL,
core.fsmonitor=, for-each-ref, rev-parse, and remote pattern.
- The dominant direct parents were active VS Code extension-host processes.
- PID 4 had accumulated more than 624,000 handles when checked.
Kernel/object analysis
Read-only Sysinternals Handle inventories and LiveKD analysis established that
the PID 4 growth is almost entirely unnamed Section handles. Representative
objects had:
- object type: Section
- no name
- access mask:
0x000f001f - one PID 4 handle
- pointer count: 32767
- one mapped view
- one 4 KB committed pagefile-backed page
The evidence supports the Codex Git-process storm as the repeatable trigger. It
does not establish that Codex itself owns or directly leaks the kernel objects;
the Windows process-creation/teardown path may retain them after the rapid
short-lived process launches.
Expected behavior
The sidebar should not continuously rescan the Git origins of a large
historical task-directory set. Background repository discovery should be
bounded, cached, cancellable when the view is inactive, and should not create
hundreds of processes per minute.
Actual behavior
The Codex sidebar repeatedly scans historical task directories, creating
hundreds of short-lived Git/conhost processes and driving sustained PID 4
Section-handle growth until the workstation approaches resource exhaustion.
Requested investigation
Please investigate:
- The refresh/invalidation loop behind
sidebar_workspace_task_groups_task_dirs.
- Whether Git-origin discovery is duplicated across multiple VS Code
extension hosts/windows.
- Whether repository results can be cached or concurrency/rate limited.
- Whether the internal sidebar Git/PR-origin functionality can be disabled
through a supported setting as a mitigation.
- Why uninstall/reinstall preserves or reconstructs the same historical
task-directory workload.
Sanitized measurements and command lines can be supplied. Full logs, ETL
traces, and live-kernel dumps exist but contain private workstation and
repository information and should not be uploaded publicly.
3 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
019f7a38-8dd7-7982-a88a-e4423a600445
@tmesias — current Codex Desktop reproduction adds a strong Desktop-side coordinate to #35775
I reproduced the same Git-origin/process-storm family you documented in #35775, but on the current Microsoft Store Codex/ChatGPT Desktop application rather than the VS Code extension. The capture is long enough, and the parent/child topology is clean enough, that I think it adds a useful coordinate for narrowing the remaining root cause rather than simply adding another “Windows is slow” report.
This also intersects the Desktop work already reported in #29949, #26812, #34260, and #35880. I am writing this here because your
requestKind=git-origins/source=sidebar_workspace_task_groups_task_dirsfinding is the closest published coordinate I have seen to the behavior in this capture.Environment
Observed on:
OpenAI.Codex_26.810.4967.0_x64https://git.chatgpt-team.site/<workspace>/<project>.gitThe system was not memory constrained and the SSD was healthy. The user-visible symptom was system-wide cursor/UI stutter while Codex Desktop was active.
40-minute process trace
I ran a read-only 40.01-minute Windows process/performance capture while Codex Desktop was being used normally for local repository work.
System summary:
The important point is that this was not a classic sustained DPC/ISR storm or a RAM exhaustion event. The dominant abnormality was process churn.
Process starts in 40 minutes:
conhost.exe: 5,832git.exe: 5,535reg.exe: 3,221node.exe: 289pwsh.exe: 135dllhost.exe: 135tzutil.exe: 72workerd.exe: 68taskkill.exe: 54gh.exe: 24rg.exe: 22cmd.exe: 19codex-windows-sandbox-setup.exe: 13git-remote-https.exe: 6git-credential-manager.exe: 6sh.exe: 6Total process starts captured by the event trace: 15,563.
That is approximately 389 process starts/minute averaged over the whole run, or about 6.5 process creations/sec continuously averaged over 40 minutes.
The average hides much larger bursts.
Peak minute
At
23:30, the trace recorded:git.execonhost.exePeak second
At
23:30:27, one single second contained 179 process starts:git.execonhost.exereg.exepwsh.exetaskkill.exesvchost.exeThis is the point I would treat as the strongest process-scheduling “vibration”: the failure is not merely an aggressive periodic poll. At peak, many repository/process discovery operations are alive in parallel within one scheduler interval.
Parent topology: the Desktop main process is a primary source
The current app is packaged under
OpenAI.Codex_26.810.4967.0.The root Desktop process in the capture was:
ChatGPT.exe, PID 13856The bundled app-server was a child:
ChatGPT.exe (13856)-> codex.exe app-serverOver the 40-minute trace, PID 13856 directly created 5,832 children.
Direct children of the Desktop main PID:
reg.exe: 3,221git.exe: 2,530taskkill.exe: 54gh.exe: 24cmd.exe: 2node.exe: 1This matters because it narrows the origin of a large part of the storm to Desktop-shell/runtime behavior rather than the
codex.exeapp-server alone.There are additional Git descendants below those direct children, which explains why total
git.execount reaches 5,535.My strongest current hypothesis is therefore not “Git itself is slow.” It is that a Desktop-side state-refresh / metadata-discovery scheduler is producing redundant concurrent work, and the Windows subprocess model amplifies that work into system-wide latency.
A second coordinate that may be under-investigated:
reg.exeThe
git.exe/conhost.exestorm is already known. The new coordinate I would look at closely is thereg.exevolume:3,221 reg.exestarts in 40 minutes.All 3,221 were direct children of the Desktop main
ChatGPT.exePID in this capture.That is too regular to dismiss as unrelated system noise.
I do not yet have the short-lived
reg.execommand lines because the process-start ETW/WMI trace captured parent/PID/name, while command-line polling was too slow for sub-second children. I would specifically capture these command lines and the Desktop JS call site.If you inspect the packaged runtime, I would search for:
reg.exeIf the same refresh generation invokes both Git-origin discovery and registry/tool discovery, this could explain why the storm remains expensive even when only part of the Git path is suppressed.
ChatGPT Sites / Credential Manager is a real but separate branch
This repository has a local remote equivalent to:
sites -> https://git.chatgpt-team.site/<redacted>/<redacted>.gitand Git uses Credential Manager.
During the same 40-minute capture I observed six complete remote-authentication helper chains.
Representative chain:
ChatGPT.exe-> git.exe-> git.exe-> git-remote-https.exe-> sh.exe-> git.exe-> git-credential-manager.exeThe six GCM starts occurred approximately:
after diagnostic start.
This is consistent with #35880: background repository metadata discovery reaches a Sites HTTPS remote and invokes GCM even though the user did not request a fetch/pull/push operation.
I would keep this logically separate from the main 5,535-Git storm:
git-remote-https/ GCM chains and the visible credential prompt.Fixing the GCM prompt alone will not fix the process storm.
Conversely, suppressing broad Git-origin probing may also eliminate the conditions that invoke GCM.
Important distinction from the empty-
.gitcaseThis capture is from a real Git repository, not only an invalid/empty
.gitplaceholder.So negative-caching invalid repositories is necessary for the empty-
.gitfailure mode, but it is not sufficient for the general storm.The current behavior also needs to be bounded for valid repositories and historical task/workspace directories.
That makes your #35775 coordinate particularly important:
requestKind=git-originssource=sidebar_workspace_task_groups_task_dirsThe question I would now answer is:
What invalidates that request, and how many logically equivalent requests can coexist before the prior one completes?
Where I would instrument next
Rather than instrumenting Git itself, I would instrument the caller immediately above the worker/request boundary.
For every
git-originsrequest, log only diagnostic metadata such as:Then compare that with process creation.
If 100+
git.exeprocesses appear inside one second, I would expect to find one of these two shapes:The second case would explain the very sharp burst shape better than a simple timer.
Specific runtime areas worth checking
The earlier #29949 investigation identified a packaged Git worker handling
git-origins, plus separate WMI/process-discovery paths. In a newer build the minified filenames may have changed, so I would locate them by stable strings rather than by old minified export names.Search the current
app.asar/.vite/buildpayload for:"git-origins""sidebar_workspace_task_groups_task_dirs"rev-parse --show-toplevelrev-parse --git-common-dirconfig --get remote.origin.urlconfig --null --get core.fsmonitorfor-each-refremote showreg.exetaskkill.exeWin32_ProcessWin32_PerfFormattedData_PerfProc_ProcessI would then map:
sidebar / thread / workspace invalidation-> task-directory collection-> canonicalization-> git-origins request-> worker fan-out-> Git subprocess spawnand separately:
command/process lifecycle-> process/registry discovery-> reg.exe / PowerShell / taskkillThe key is to identify whether these are independent periodic systems or whether one UI/workspace state mutation causes multiple discovery subsystems to refresh together.
Canonicalization boundary
For Git-origin discovery, deduplication should happen on repository identity, not only the raw task-directory string.
I would test canonicalization across:
A list containing 100 historical task directories should not produce 100 independent full Git-discovery sequences when most resolve to the same small set of repositories.
Possible stable cache key:
canonical Git common-dir + relevant config mtime/generationrather than:
raw task cwdSingle-flight / cancellation boundary
The next concrete intervention I would test is:
git-originscalculation per canonical repository set/generation;The acceptance metric should be process creation proportional to unique repositories whose state actually changed, not proportional to sidebar refresh count, historical task count, or command lifecycle count.
Remote default-branch / Sites rule
Background UI metadata must not require network authentication.
For a
sites/sites-originHTTPS remote, ordinary sidebar/chat refresh should not invoke a networkedgit remote show.If local metadata cannot establish the remote default branch, returning “unknown/not cached” is preferable to:
background UI refresh -> remote HTTPS -> GCMThe background path should use local Git config/refs only. A network operation should require an explicit user/agent action or an explicitly designed remote-refresh path.
A focused regression invariant would be:
Sending a normal chat message in a workspace containing a ChatGPT Sites remote must produce zero
git-remote-https.exeand zerogit-credential-manager.exechildren unless a remote Git operation was explicitly requested.taskkill.exemay be a feedback amplifierThis capture saw 54
taskkill.exestarts, all direct children of the Desktop main process.That is not the dominant storm in this machine, but given #34260 I would check whether subprocess churn causes repeated cleanup work and whether slow cleanup then creates a secondary feedback loop.
For the cleanup boundary:
Controlled intervention matrix
To avoid conflating multiple Windows failure modes, I would run four isolated A/B interventions on the current build.
A — Git-origin scheduling only
Keep all other behavior unchanged.
Change only:
Measure:
git.execonhost.exeB — network-free background remote metadata
Keep local origin discovery enabled.
Change only:
remote shownetwork path;Expected result:
git-remote-https.exe = 0git-credential-manager.exe = 0during ordinary chat/sidebar activity.
This may not materially reduce the thousands of local Git starts, and that is useful separation.
C — registry/tool discovery
Keep Git behavior unchanged.
Suppress/cache only the Desktop path responsible for the repeated
reg.exestarts.Expected result:
reg.exechildren collapse from thousands toward a small bounded number.This would tell us whether registry discovery is another independent contributor to UI input pressure.
D — process cleanup
Keep A/B/C stock.
Bound only
taskkill/ tree cleanup.Expected result:
Current-build regression value
The strongest reason I am posting this is that the failure family is still reproducible on:
OpenAI.Codex_26.810.4967.0_x64That is substantially newer than the builds discussed in the June/July reports.
The earlier #29949 copied-runtime intervention was strong evidence that suppressing Desktop WMI/Git discovery could materially reduce input delay. This new capture shows that the current Desktop build can still enter an extremely high Git/console/registry process-creation regime.
So I would not treat the July findings as historical only.
What this trace does and does not prove
It proves:
ChatGPT.exeis a direct parent of thousands ofgit.exeandreg.exestarts;It does not yet prove:
reg.exestart belongs to the same refresh generation asgit-origins;Those are exactly the next points I would instrument rather than infer.
Suggested upstream acceptance tests
I would add Windows regression budgets at the product level:
.gitgit-remote-httpsand no GCM.If useful, I can provide a sanitized table of process-start timestamps, parent PIDs and the 40-minute system summary. I would not publish the raw bundle unchanged because it contains local workstation/repository metadata.
I think the highest-yield place to look now is the Desktop-side invalidation/scheduling layer above
git-origins, not Git for Windows itself: specifically howsidebar_workspace_task_groups_task_dirs(or its Desktop equivalent) is generated, deduplicated, invalidated, and allowed to overlap with prior generations. The 3,221 directreg.exestarts are the second coordinate I would inspect in parallel because they suggest another Desktop refresh path may be participating in the same amplification.