You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Closest existing report is #4182, which mentioned this probe among several CPU problems. It was closed as fixed by #2679, but that PR replaced the process-diagnostics polling only; the changed-files list contains no PortScanner.ts, and the code below is unchanged on current main. Filing this as a focused issue for the remaining path.
Area
apps/server
Steps to reproduce
On a Windows machine, time the exact probe command from apps/server/src/preview/PortScanner.ts (line 243):
The bug triggers whenever this exceeds the scanner's 5 s timeout (WINDOWS_LISTENER_TIMEOUT_MS, line 55). On my machine it takes 48.2 s with 89 listening sockets.
If it finishes under 5 s on your machine, open artificial listeners in a separate PowerShell window and re-run the timing. The cost is per listener (roughly half a second each on my machine), so a few hundred is plenty:
Verified here: adding these 300 listeners took the probe from 48.2 s (89 listeners) to 215.2 s (390 listeners), i.e. linear in listener count.
Start T3 Code (Alpha) and leave it open with a session active.
Watch process creation (Process Explorer), or count probe launches in the classic "Windows PowerShell" event log, where event 400 records the full command line:
The probe completes well inside its timeout (it can: see the breakdown below, the same data is obtainable in under 1 s on this machine).
If a probe does time out repeatedly, the scanner backs off or stops paying for it, rather than re-running a probe that can never succeed at full cost forever. The cheap probeCommonPorts() fallback already exists.
Actual behavior
PortScanner.ts polls every 3 s (POLL_INTERVAL, line 53). Each tick spawns the PowerShell probe with a 5 s timeout. On this machine the probe needs ~48 s, so it is killed at 5 s, the timeout error is caught and only logged at debug level (recoverProcessProbeFailure), the cheap fallback runs instead, and 3 s later the next doomed probe spawns. Nothing surfaces to the user; it just repeats for as long as the app is open: 264 probe launches in the last hour, one every ~11 s (log query above; polling pauses only while no client is using port discovery).
Get-NetTCPConnection reads its data through WMI (the Windows service other tools also use to read process and system information), so every probe spins up WMI's worker process, WmiPrvSE.exe, and killing probes mid-query leaves a stream of errors in the WMI event log. Because each killed probe's WMI query keeps running server-side for tens of seconds while new probes launch every ~11 s, several queries are always in flight, and the cost shows up as a constant plateau rather than spikes: sampled at 1 s intervals over 40 s while the app was open, WmiPrvSE instances held a steady 4–6.5% of this 32-thread machine, roughly one and a half to two full cores, continuously. The symptom for the user is the one described in #4182: constant background CPU, fan noise, and system-wide stutter, because anything else that reads process information through WMI has to queue behind these queries.
Why the probe is slow: the per-connection Get-Process -Id is the cost, not the connection enumeration. Measured on the same machine (88 listeners, ~670 processes):
Step
Time
Get-NetTCPConnection -State Listen alone
0.8 s
One Get-Process call building a PID→name map
0.1 s
Formatting all 88 output lines from that map
0.02 s
A single Get-Process -Id call
0.38 s
The shipped command makes that last call once per listener, sequentially: 88 × ~0.4 s ≈ 33 s, plus PowerShell start-up and enumeration, matching the observed 48 s. Cost scales with listeners × total process count, so busy developer machines are hit hardest.
Impact
Major degradation or frequent failure
Version or commit
0.0.32 (stable). Code unchanged on main: apps/server/src/preview/PortScanner.ts lines 53–55 and 240–263.
Environment
Windows 10 Pro 19045, T3 Code (Alpha) desktop 0.0.32, Ryzen 9 7950X3D, ~670 running processes, ~90 listening TCP sockets (several dev servers and agent tooling).
None user-facing. Quitting T3 Code stops the loop. Patching bin.mjs is possible but reverts on every update.
Suggested fix
Make the probe cheap: build the PID→name map once instead of calling Get-Process -Id per connection. Same output format, measured under 1 s on the machine where the current command takes 48 s:
Even with a faster probe, add a backstop: after several consecutive timeouts, poll less often or stop attempting the expensive probe and stay on probeCommonPorts(). A probe that has timed out every 3 s for an hour will not succeed on the next tick.
On a machine set up as in the repro (or with the 300 artificial listeners): run the app for 10 minutes, then run the event-log query from step 4. Fixed means the probes now complete within the timeout: no more launch every ~11 s (at most one per 3 s tick while port discovery is in use), no sustained WmiPrvSE.exe CPU, and no new "could not send status to client" errors in the WMI-Activity event log.
Before submitting
Area
apps/server
Steps to reproduce
apps/server/src/preview/PortScanner.ts(line 243):WINDOWS_LISTENER_TIMEOUT_MS, line 55). On my machine it takes 48.2 s with 89 listening sockets.Expected behavior
probeCommonPorts()fallback already exists.Actual behavior
PortScanner.tspolls every 3 s (POLL_INTERVAL, line 53). Each tick spawns the PowerShell probe with a 5 s timeout. On this machine the probe needs ~48 s, so it is killed at 5 s, the timeout error is caught and only logged at debug level (recoverProcessProbeFailure), the cheap fallback runs instead, and 3 s later the next doomed probe spawns. Nothing surfaces to the user; it just repeats for as long as the app is open: 264 probe launches in the last hour, one every ~11 s (log query above; polling pauses only while no client is using port discovery).Get-NetTCPConnectionreads its data through WMI (the Windows service other tools also use to read process and system information), so every probe spins up WMI's worker process, WmiPrvSE.exe, and killing probes mid-query leaves a stream of errors in the WMI event log. Because each killed probe's WMI query keeps running server-side for tens of seconds while new probes launch every ~11 s, several queries are always in flight, and the cost shows up as a constant plateau rather than spikes: sampled at 1 s intervals over 40 s while the app was open, WmiPrvSE instances held a steady 4–6.5% of this 32-thread machine, roughly one and a half to two full cores, continuously. The symptom for the user is the one described in #4182: constant background CPU, fan noise, and system-wide stutter, because anything else that reads process information through WMI has to queue behind these queries.Why the probe is slow: the per-connection
Get-Process -Idis the cost, not the connection enumeration. Measured on the same machine (88 listeners, ~670 processes):Get-NetTCPConnection -State ListenaloneGet-Processcall building a PID→name mapGet-Process -IdcallThe shipped command makes that last call once per listener, sequentially: 88 × ~0.4 s ≈ 33 s, plus PowerShell start-up and enumeration, matching the observed 48 s. Cost scales with listeners × total process count, so busy developer machines are hit hardest.
Impact
Major degradation or frequent failure
Version or commit
0.0.32 (stable). Code unchanged on
main:apps/server/src/preview/PortScanner.tslines 53–55 and 240–263.Environment
Windows 10 Pro 19045, T3 Code (Alpha) desktop 0.0.32, Ryzen 9 7950X3D, ~670 running processes, ~90 listening TCP sockets (several dev servers and agent tooling).
Logs or stack traces
Workaround
None user-facing. Quitting T3 Code stops the loop. Patching
bin.mjsis possible but reverts on every update.Suggested fix
Get-Process -Idper connection. Same output format, measured under 1 s on the machine where the current command takes 48 s:probeCommonPorts(). A probe that has timed out every 3 s for an hour will not succeed on the next tick.GetExtendedTcpTable), for example via thet3-resource-monitorbinary introduced in Reduce idle work and disk churn with native resource diagnostics #2679. That avoids spawning PowerShell and touching WMI at all, which is exactly what Reduce idle work and disk churn with native resource diagnostics #2679 already did for process diagnostics.How to verify a fix
On a machine set up as in the repro (or with the 300 artificial listeners): run the app for 10 minutes, then run the event-log query from step 4. Fixed means the probes now complete within the timeout: no more launch every ~11 s (at most one per 3 s tick while port discovery is in use), no sustained WmiPrvSE.exe CPU, and no new "could not send status to client" errors in the WMI-Activity event log.