[Windows 10] DWM Composition handles accumulate after Codex tasks with tool calls
Summary
On Windows 10 22H2, I can reproduce persistent growth in DWM's Composition handle count after Codex tasks that make terminal tool calls. A no-tool task that replied only OK did not show the same growth. In one controlled five-call run, the Composition count increased by 22 and remained elevated throughout the 30-second period after the task finished.
After about four days of normal Codex use, DWM had 22,770 Composition handles, compared with 817 after a DWM restart. At that point, dragging an ordinary window could lag by 10 to 20 seconds. Restarting only DWM cleared the accumulated state and immediately restored smooth window movement.
In a separate control, every ChatGPT.exe and codex.exe process was absent for about 5 minutes 35 seconds. No comparable new growth was observed while Codex was closed, but the handles already held by DWM did not fall. So far, they have only been cleared by restarting DWM or Windows.
I cannot yet tell whether the lifetime problem begins in the Codex UI, Electron, Chromium, DirectComposition, DWM, or the graphics driver. This report documents the repeatable trigger and the resource signature.
Environment
- Windows 10 22H2, build
19045.7417, x64 - Codex MSIX
OpenAI.Codex_26.707.9981.0_x64 - Internal app version
26.707.72221, build5307 - Electron
42.1.0 - Chromium/ProductVersion
150.0.7871.115 - One internal display at
2400 x 1600, 60 Hz; no external display - Intel Iris Xe Graphics and NVIDIA GeForce RTX 3050 Ti Laptop GPU
- HAGS enabled (
HwSchMode=2) - Variable refresh optimization enabled (
VRROptimizeEnable=1) - MPO disabled (
OverlayTestMode=5)
I have seen the same general problem across several Codex desktop updates. The version above is the one used for the controlled captures below.
Reproduction
- Start from a low DWM handle count after signing in to Windows or restarting DWM.
- Open Codex and create a new task.
- Ask it to make several separate, read-only terminal calls, for example:
``powershell``
Get-Date
Get-Location
Get-Process -Id $PID | Select-Object Id, ProcessName, HandleCount
git status --short
Get-ChildItem -Name | Select-Object -First 3
- Record the count and type of DWM handles before the task, while it runs, and for at least 30 seconds after it finishes.
- Repeat the task a few times. It is not necessary to keep Codex in the foreground.
- For comparison, create a new task that only replies
OKand does not call any tools.
Expected: After a task finishes and its status UI settles, DWM Composition handles should return close to their previous baseline.
Actual: Tasks with several tool calls leave a small persistent net increase. Repeating these task cycles gradually builds a much larger DWM-side handle stock.
Controlled results
| Test | Workload | Persistent DWM handle change | Composition change |
| --- | --- | ---: | ---: |
| Plain text control | New task replied only OK; no tools | +5 | -1 |
| Five terminal calls | Five separate read-only calls | +10 | +22 |
| Idle long task view | Visible and idle for about 10 minutes | +2 | Not sampled by type |
| Idle short task view | Visible and idle for about 10 minutes | 0 | Not sampled by type |
| Active task | Running for about 6 minutes | +66 | Not sampled by type |
| Active task, Codex minimized | Running in the background | +55 | Not sampled by type |
| Scheduled task | Natural unattended run | +88 | Not sampled by type |
The two controlled runs used 30-second medians before and after the task. The DWM PID remained unchanged.
DirectComposition trace
I captured the five-call test with the Microsoft-Windows-DirectComposition and Dwm-Core ETW providers.
During the server-reported task interval, DirectComposition recorded four identical 12-resource creation batches for DWM channel 61. None of those 48 resources had a matching release before the trace ended. An identical fifth batch appeared about 2.1 seconds before the server startedAt timestamp, which may reflect local task initialization, but I cannot prove that from this trace.
Every batch had this resource type sequence:
201, 195, 195, 32, 32, 79, 87, 39, 58, 39, 58, 30
The resource handles were sequential and had openShared=false.
This capture did not include the Dwm-Core channel-attribution keywords, so I cannot map channel 61 to a specific client PID. The same batch signature also appeared occasionally outside the task interval. I therefore treat this as a correlation clue rather than proof that channel 61 belongs to Codex.
The capture used Dwm-Core keyword mask 0x21. A follow-up trace should use 0x900021 so that it also records PROCESS_ATTRIBUTION, CHANNEL_OPENED_FOR_PROCESS, CHANNEL_CLOSED_FOR_PROCESS, and COMMAND_PROCESSED_ONBEHALF. The DirectComposition mask can remain 0x5F.
DWM kept the same PID throughout the run. There was no lock-screen transition. Video.UI emitted no DirectComposition create or release events during the task interval, and the ShellExperienceHost burst began only after completion, consistent with the completion notification.
Related report
The closest existing report I found is #16374, which describes progressive Windows shell freezes associated with Codex. This may be part of the same broader problem. The additional evidence here is the DWM handle type, the no-tool control, and the DirectComposition capture.
Package note
The affected package is an Electron 42 and Chromium 150 application, not WebView2. I found task-status and sidebar lifecycle code in the packaged ASAR, but the production package has no source maps, so I could not map the observed resource lifetime to a specific source module.
Evidence retained locally
The most relevant sanitized results are included above. I have also kept the complete ETL, the two run summaries, before-and-after handle type diffs, and the extracted DirectComposition batches. I have not attached the raw ETL because it contains a wider process timeline.
13 Comments
This issue also affects the CLI version of Codex, and it has been like this at least since 0.13*
I let Codex analyze the issue and it figured out that it may relate to this commit:
https://github.com/openai/codex/commit/6b3d82daca540318d074c1ad2afcaba5b3337a3d
... which creates a private desktop per tool call and ignores the return value when it is closed. I am testing a custom build where a shared/reused private desktop is used and will report back
Codex created this patch. I deployed the executables and ran thousands of tool calls. The memory and CPU consumption of dwm.exe did not move.
The main cause seems to be that every tool call creates a dedicated private desktop and it's closure is neither checked nor retried.
The attached patch, based on 0.144.5, creates one private desktop per Codex process.
codex-0.144.5-shared-private-desktop.patch
10 hours later with 4 agents running in parallel - dwm still only reports 46 MB, load sub 0.1%, all windows are snappy... the main issue is really the desktop creation per tool call and the missing cleanup, or there is a leak in dwm.exe itself.
Adding another Windows reproduction on a current desktop build.
Environment
26.721.4979.026200.8875(25H2)Symptom
This is system-wide compositor/input lag, not only a slow Codex window:
Resource headroom
A live read-only snapshot during the affected session showed approximately:
taskkill.exeorconhost.exeprocessesThis therefore did not coincide with conventional CPU or physical-memory exhaustion.
The symptom is materially similar to the delayed ordinary-window dragging reported in this issue. It may also overlap with long-thread renderer/event-state growth discussed in #21134, but the important distinction here is that the rest of Windows becomes nearly unusable too.
Expected behavior
Long-running local Codex workflows should not degrade Windows DWM/compositor or system-wide input responsiveness when the machine retains substantial CPU and RAM headroom. DirectComposition/DWM and renderer resources should remain bounded and be released during prolonged background work.
Private prompts, project names, session identifiers, filesystem paths, and raw logs are intentionally omitted. Privacy-safe diagnostics can be collected through the official feedback channel if maintainers specify what additional counters or trace profile would be useful.
Confirming this is still unfixed in the current Store build, with a concrete Windows 10 reproduction.
Environment
OpenAI.Codex_26.803.5235.0_x64__2p2nqsd0c76g0(current as of Aug 6)app\resources\codex.exestill importsCreateDesktopW/CloseDesktop, and the sandbox helper (codex-command-runner.exe) still accepts--windows-sandbox-private-desktopand is re-copied into%USERPROFILE%\.codex\.sandbox-bin\on every launch.Observed behavior
dwm.execlears the handles and immediately restores responsiveness. Nothing else does - not a GPU driver reset, not killing the renderer tree.Timeline impact
This has been slowing my PC down for literally 6-7 months. I have been trying to figure out what has been happening the whole time, and it has been progressively getting worse. This needs to be fixed ASAP please - it is killing my PC.
What would help
CreateDesktopWper command, close result ignored, no retry. The shared-private-desktop patch in this thread (one desktop per process) is a validated direction - thousands of tool calls with zero DWM growth, 10h/4-agent run with DWM at 46 MB.CloseDesktop, or expose a supported toggle that stops per-call desktop creation without losing the sandbox isolation. Note that the existingwindows.sandbox_private_desktop = falseescape hatch does not preserve the isolation - it disables it entirely.Happy to provide a WPR/ETW trace or Process Monitor capture on request. This has been open since July 14 and is still affecting current builds - it's the difference between Codex being usable and not on Windows 10.
Adding DWM-side object counts that quantify this per tool call, plus where the CPU actually goes.
Environment
26200(25H2), x64, 24 logical cores, 64 GiB RAMOpenAI.Codex_26.803.5235.0_x64__2p2nqsd0c76g032.0.16.1088Method
Rather than counting kernel handles, I dumped
dwm.exe(full memory,MiniDumpWriteDump)and counted live composition objects by scanning for their vtable addresses:
Tool-call counts come from
~/.codex/.sandbox/sandbox.<date>.log, countingsetup refresh: spawning ...codex-windows-sandbox-setup.exeoccurrences inside eachmeasurement window.
Both measurements below were taken against the same
dwm.exeinstance (PID unchanged),with Codex fully exited before the closing measurement in each case. No other
application was started, closed, or resized during either window.
Results: the leak is a constant per tool call
| | Run 1 | Run 2 |
| --- | ---: | ---: |
| Wall-clock window | 34 min | 177 min |
| Sandboxed command executions | 395 | 359 |
|
CVisualdelta | +2,393 | +2,182 ||
CDesktopTreeDatadelta | +2,395 | +2,183 ||
CVisualOcclusionInfodelta | +501 | +391 ||
CVisualper tool call | 6.06 | 6.08 ||
CDesktopTreeDataper tool call | 6.06 | 6.08 |The per-tool-call figure reproduces to within 0.3% across two runs whose durations
differ by 5x. The leak tracks tool-call count, not session length or wall-clock time.
CVisualandCDesktopTreeDatastay locked at 1:1 throughout.None of it is released when Codex exits. Both closing measurements were taken with no
ChatGPT.exe/codex.exeprocess running; the counts above are what remained.For scale, immediately after a
dwm.exerestart this machine sits at 4,752CVisual.Two Codex sessions took it to 9,487 - roughly doubling the entire desktop's composition
tree from ~750 tool calls.
Where the CPU goes
Sampled profile of
dwm.exe(xperf -on PROC_THREAD+LOADER+PROFILE -stackwalk profile,symbols from the public server) once the tree had grown large, showing why this presents
as system-wide lag rather than a Codex-only problem:
DWM walks the visual tree three times per frame plus a transform pre-walk, all O(visual
count). Under 8% of its time is spent actually drawing or presenting - the rest is
bookkeeping over the accumulated tree. On this machine that reached ~90% of one CPU core
with the compositor otherwise idle, and restarting
dwm.exereturned it to ~7%.Happy to re-run with additional counters if that would be useful.
Confirming that this is still happening on a newer Windows Store build.
Environment
26.803.10989.0(app-server0.147.0-alpha.6.6)2620032.0.101.6881and NVIDIA RTX 4060 Laptop GPUWhat happens
After Codex has been running tool-heavy tasks for many hours, the mouse pointer starts moving in visible steps across the desktop and other applications. The rest of Windows remains responsive. Signing out of Windows or rebooting restores smooth pointer movement, but the problem returns after another long Codex session.
During one affected session, Codex and Windows had been running for about 28 hours. The sandbox log contained 9,688 launches of
codex-windows-sandbox-setup.exe. At that point:dwm.exewas using 749–766 MiB of private memory and had about 994 MiB of GPU memory committed.This does not look like ordinary CPU or memory pressure, and it matches the DWM accumulation described in this issue.
Why the private-desktop cleanup still looks relevant
The current code still creates a fresh randomized
CodexSandboxDesktop-*for a sandboxed process:LaunchDesktop::prepare(...).PrivateDesktop::createcallsCreateDesktopW.CloseDesktop.Together with the repeatable per-tool-call
CVisualandCDesktopTreeDatagrowth reported above, this points to the same failure mode: private desktops are created repeatedly, some composition state is not released, and DWM gradually has more work to do each frame.A fix should keep the number of private desktops bounded or verify that desktop cleanup actually succeeds and that the related DWM objects return to baseline.
Same issue with win UI lag happening with me also with Codex left running for half a day.
A force kill of dwm.exe is needed to restart it and get the UI back to a normal state.
Title: Windows-wide mouse/input stutter persists after opening a second Codex window until all ChatGPT.exe processes are terminated
I am seeing intermittent system-wide mouse/input stutter on Windows while using Codex in the ChatGPT Desktop app. Chrome, File Explorer, and Codex are all affected. An unusual observation is that putting Task Manager in the foreground makes mouse movement feel smooth across the desktop, even when the Task Manager window is small.
The clearest reproduction I have observed is:
ChatGPT.exeprocesses in Task Manager. The system immediately becomes smooth.This does not appear to be reliably caused by running two tasks or by web preview itself. Opening the second window appears to trigger or expose a background app-process state that remains after the UI windows are closed.
Read-only snapshots during the lag did not show general resource saturation: CPU was about 15% average (20% peak), DPC about 0.11% average, and interrupts about 0.63% average. The ChatGPT group had about 13 processes and about 3.19 GB private memory. A ChatGPT GPU process used about 10% average / 24% peak 3D, while
dwm.exeused about 2.7% average / 3.9% peak. I saw no display-driver reset, DWM, or WHEA error around the second-window reproduction time.Hardware: 32 GB RAM, NVIDIA RTX 4060 + Intel UHD 770, 60 Hz display. Windows reports build 26200.8875. I also saw one earlier WER
RADAR_PRE_LEAK_64event forChatGPT.exe, but I cannot prove that it is related.Could you please investigate whether the Windows desktop app can leave an Electron/Chromium renderer, GPU-process, DirectComposition, or DWM-composition state active after opening a second window or running Codex tools? This is a hypothesis based on the observed behavior, not a confirmed root cause.
I can provide a sanitized diagnostic summary. I have not captured an ETW trace yet because Windows Performance Recorder requires an elevated administrator session.
Additional sanitized evidence for #33192
No raw ETL, CSV export, screenshot, process tree, command line, or machine-specific path is attached. All times below are relative to the retained trace interval.
Reproduction on a newer build
26.810.4967.0codex-command-runner-0.148.0-alpha.9.exeCompositionchange:+18, exactly+2per runner invocationThis reproduces the issue on a newer package than the one in the original report.
ETW handle-lifetime evidence
A separate retained ETW slice from package
26.803.10989.0and command runner0.147.0-alpha.6.6contained:Compositioncreation burstsWindowUpdateevents within 50 msWindowUpdateevents fell inside those matched burst windowsThe observed enrichment of runner
WindowUpdateevents around DWM creation bursts was approximately 80x over a uniform-background expectation at a 50 ms window.Symbolized creation path
The repeated DWM-side creation path was:
Interpretation
The evidence points to per-command Windows sandbox runner lifecycle as the trigger. Each short-lived runner produces a Win32k window update that is followed within milliseconds by DWM desktop/global-light-set creation, with two Composition objects remaining outstanding after the runner exits.
The trace does not establish whether the missing release belongs in the runner, console/window lifecycle, DirectComposition interop, or DWM itself. It does narrow the trigger from the general Codex UI to the per-command Windows runner path.
Adding sanitized evidence from the current Store package. This confirms that the system-wide DWM bottleneck is still present on a build newer than the ones above, while also showing that a short total-handle test does not reproduce the lifetime signature every time.
Environment
OpenAI.Codex_26.818.5229.0_x64151.0.7922.17026200, 24 logical processors, 96 GiB RAM32.0.16.1088HwSchMode=2); noOverlayTestModeMPO overrideThe symptom is Windows-wide window-drag/input stutter, not merely a slow Codex window. It persisted with substantial CPU/RAM headroom and low GPU, disk, DPC, and interrupt activity. It also reproduced at 144 Hz after the emulator device process had exited, so the emulator is not a necessary condition.
WPR/ETW evidence on
26.818.5229.0I captured the affected drag interval with the Microsoft
CPU.Verbose + DesktopComposition.LightWPR profiles, then decoded it with WPA/Xperf. The analysis interval was restricted to the actual 21.5-second drag action (0.5-22.0 s), excluding trace-save work.85.93%of total CPU capacity as Idle.dwm.exeaveraged0.99logical core.85.50%of DWM sampled CPU;87.10%of that thread's exclusive samples were indwmcore.dll.8.73 us; sustained scheduler starvation was not present.1.96% / 0.57%of that DWM frame thread. GPU work was not saturated, and no third-party display/overlay module appeared in the hot path.ChatGPT.exeprocesses together averaged about0.56logical core; no single Codex process saturated a core.An earlier lossless
DesktopComposition.Lightcapture over an 18.482-second DWM root region showed:ProcessFrame:14.097 sPresent:7.477 sOcclusion:4.169 sPreCompute:2.935 sVSyncDPC:142.35/s, matching the 143.85 Hz display modeThis independently matches the DWM-side CPU shape reported above: the user-visible failure is a serial composition/frame-thread bottleneck while the rest of the machine remains mostly idle.
Mitigation A/B
Disabling “Show window contents while dragging” at 144 Hz reduced:
169.67% -> 76.93%on a one-core-equals-100% scale (-54.7%)45.21% -> 16.35%(-63.8%)190,638/s -> 43,261/s(-77.3%)This is a useful workaround, not a fix: DWM still remained around
0.77core, and the user must give up live window contents. Reducing the display to 60 Hz also improves usability but does not eliminate the DWM bottleneck.Short handle control on the current build
I also ran two controlled five-terminal-call batches while sampling DWM's total handle count:
2392 -> 2391(range2391-2394)+45versus baseline), followed by recovery toward23952424to2395and remained there through the end811 / 674 MiBduring this short testThis test did not enumerate the
Compositionhandle type, so it does not disprove the typed per-runner leak documented in the comments above. It does show that the short-run total-handle signature is state-dependent on26.818.5229.0, while the DWM frame-thread performance failure remains reproducible.Request
Please keep investigating this against the current Windows desktop package rather than treating it as limited to the older builds. I retained the original 1.71 GiB CPU+composition ETL and sanitized WPA/Xperf exports locally. I have not attached the raw ETL because it contains a wider process timeline. If maintainers provide a privacy-safe upload route and specify the desired provider/keyword set, I can supply the trace or repeat a targeted capture.
How is this issue not considered a _very_ high priority yet? I installed the app for the first time and genuinely thought something was wrong with my PC because the entire Windows desktop became increasingly unusable after only a few hours, even when closing every software (including GPT).
After finding this thread, I’m pretty shocked to see reports going back this far without any visible indication that the issue has been elevated.
In my case, restarting dwm.exe immediately fixes the system-wide lag, while Codex can remain open. CPU, GPU and memory usage are all low. The apparent handle/composition-resource leak also means the problem is accumulating long before the desktop becomes noticeably unusable.
I also asked several friends who use the Windows app, and every single one of them confirmed experiencing the same degradation.
This makes the Windows app effectively unusable for me and seriously makes me consider uninstalling it again. Is this being actively investigated / treated as a high-priority issue?