Skip to content

pet server configure hangs in a filesystem-scan busy-loop on large workspaces → 30s timeout × 3 retries = ~90s 100% CPU (thermal shutdown on laptops) #1747

Description

@calibrator2026

Summary

The pet binary (python-env-tools, shipped by ms-python.vscode-python-envs) busy-loops inside a filesystem stat/close scan when handling a configure JSON-RPC request whose environmentDirectories glob is evaluated against a large workspace. The scan does not complete within the extension's 30-second configure timeout, so the extension kills pet (SIGTERM), restarts it, and re-sends configure — which hangs again. After 3 attempts (~90 s of sustained 100% CPU on one core) the extension gives up.

On a thermally-constrained laptop this ~90 s 100% CPU spike pushes the package past 105 °C and the embedded controller cuts power with no OS-level log (no OOM, no panic, no thermal trip in journald — the journal just ends mid-normal-activity). The bug therefore masquerades as a hardware/BIOS issue and is very hard to diagnose. Worth fixing for that reason alone, not just the wasted CPU.

Environment

  • Extension: ms-python.vscode-python-envs v1.20.1 — the latest version compatible with my VS Code. (I have 1.22.0–1.36.0 installed too, but VS Code refuses to load them: "Extension is not compatible with Code 1.108.1. Extension requires: ^1.110.0-20260204". So I can't test newer versions without also upgrading VS Code. Happy to re-test on 1.36.0 if a maintainer confirms whether the scan/timeout behavior changed.)
  • VS Code: 1.108.1
  • OS: Ubuntu 24.04.3 LTS, kernel 6.17.0-22-generic, x86_64
  • pet binary: ELF 64-bit, static-pie, with debug_info, not stripped
  • Hardware: HP OMEN laptop, Intel Core Ultra (Arrow Lake-H) + NVIDIA RTX 5070 Laptop (degraded cooling — needs repaste)

The trigger workspace

The crash only happens for one of my open workspaces. Its size is the key:

$ find /home/<user>/workspace/large-project | wc -l
279488
$ du -sh /home/<user>/workspace/large-project
101G

279,488 files / 101 GB, including several node_modules trees with symlinks. The other workspaces I have open (346 / ~small files) configure in <1 s and never spin. The configure params the extension sends for this workspace:

{"workspaceDirectories":["/home/<user>/workspace/large-project"],
 "environmentDirectories":["/home/<user>/workspace/large-project/**/.venv"],
 "pipenvExecutable":"pipenv","poetryExecutable":"poetry",
 "cacheDirectory":".../pythonLocator"}

Note the **/.venv glob — pet walks the entire 279k-file tree looking for .venv dirs.

Reproduction (CLI, deterministic, ~12 s)

pet server reads JSON-RPC over stdio with Content-Length framing. Sending the exact configure request the extension sends hangs pet in a stat/close scan loop:

$ # request body in configure.json (the JSON above)
$ ( printf "Content-Length: %s\n\n" "$(wc -c < configure.json)"; cat configure.json; sleep 13 ) \
    | timeout -s INT 12 strace -c -f -e trace=futex,poll,ppoll,read,write,stat,newfstatat,openat,close \
      ~/.vscode/extensions/ms-python.vscode-python-envs-1.20.1-linux-x64/python-env-tools/bin/pet server
# exit code 124  (pet never responded within 12 s)

strace summary (12 s, no pet find, just configure):

% time     seconds  usecs/call     calls    errors syscall
 72.50    0.203708           1    138906           close
 27.50    0.077264          11      6792      4317 stat
  0.00    0.000000           0         1           read
  0.00    0.000000           0         1           poll
100.00    0.280972          1    145700      4317 total

So pet is in a tight stat/close loop walking the workspace, 64% of stats returning ENOENT (probing for .venv/python/etc. at every entry). 12 s wasn't enough to finish; the extension's 30 s timeout isn't either.

Extension log (from the actual crash session)

~/.config/Code/logs/20260829T164624/window2/exthost/ms-python.vscode-python-envs/Python Environments.log:

16:47:32.185 [info] [pet] Starting Python Locator .../pet server
16:47:32.186 [info] [pet] configure: Sending configuration update: {"workspaceDirectories":[".../<large-workspace>"],"environmentDirectories":[".../<large-workspace>/**/.venv"],...}
16:48:02.186 [warning] [pet] Configure request timed out, killing hung process for restart
16:48:02.186 [error]  [pet] configure: Configuration error Request 'configure' timed out after 30000ms
16:48:02.187 [warning] [pet] Restarting Python Environment Tools (attempt 3/3, waiting 4000ms)
16:48:02.188 [error]  [pet] Python Environment Tools exited unexpectedly with code null, signal SIGTERM
16:48:06.195 [info] [pet] Starting Python Locator .../pet server     # restart, send configure again
16:48:36.197 [warning] [pet] Configure request timed out, killing hung process for restart   # 30s later, again
16:48:36.197 [error]  PET failed after 3 restart attempts.
16:48:36.199 [warning] [priorityChain] .../<large-workspace> defaultInterpreterPath '/bin/python3' unresolvable, falling back to auto-discovery

Same pattern reproduces every time this workspace is opened (also seen in the 20260829T213146 session). Other workspaces configure in <1 s.

Impact / why this matters

Secondary issue: pet busy-loops on malformed input too

While figuring out the framing I sent a request without a valid Content-Length header. Instead of failing gracefully, pet entered an infinite error-spam loop writing the same error to stderr — 941,762 write calls in 12 s (~78k writes/s), 100% CPU:

% time  calls    syscall
 58%   941762   write
 24%    98908   open
 11%   188354   read
  ...

stderr was the error message recursively nesting itself. A malformed request should error once and continue, not spin. Likely the same lack of backoff/bounding that causes the configure hang.

What I'd suggest (and can help validate)

  1. Bound the configure scan: skip / prune common heavy dirs (node_modules, .git, __pycache__, .venv contents), cap depth or entry count, or make discovery incremental/lazy instead of a full synchronous walk that must finish before configure responds.
  2. Don't retry 3× with no backoff: a workspace that times out once will time out 3 times — that's 90 s of guaranteed 100% CPU. Exponential backoff or a single retry would cut the blast radius.
  3. Fix the error-spam loop on malformed input (fail once, don't busy-write).
  4. If a maintainer can tell me which pet subcommand/request path is the right one to exercise, I can attach a perf record call graph (I have perf + the binary's debug symbols ready, just need to temporarily relax perf_event_paranoid). The strace above already localizes it to the env-discovery glob scan, but a flamegraph would pin the exact function.

Workaround

Disable / uninstall the ms-python.vscode-python-envs extension, or avoid opening the large workspace, or narrow python.envs.environmentDirectories so the glob doesn't span the whole tree.

Related

Activity

  1. eleanorjboyd commented on Sep 23, 2026

    @eleanorjboyd
    Member

    🤖 Thanks for the detailed investigation. The default for python-envs.workspaceSearchPaths has since changed from the recursive ./**/.venv to [".venv", "*/.venv"] (starting in v1.28.0), so current releases no longer search every depth of the workspace by default. This setting can still be explicitly overridden, so it is worth checking the workspace-folder, workspace, and user settings for a remaining **/.venv pattern. On v1.20.1, explicitly setting python-envs.workspaceSearchPaths to [".venv", "*/.venv"] may avoid the costly scan if your environments are at those depths. We have also changed configure timeout handling since 1.20.1, though that alone does not make a recursive glob inexpensive.

  2. eleanorjboyd commented on Sep 30, 2026

    @eleanorjboyd
    Member

    We’ve changed the default environment search paths and configure-timeout handling since the version you reported. Could you update to the latest Python Environments release and retry? Please check your python-envs.workspaceSearchPaths setting specifically in case that wasn't overriden.

    If it still happens with [".venv", "*/.venv"], please share fresh Python Environments trace logs and your extension version. If we don’t hear back within seven days, we’ll close this for now; we can reopen it with updated diagnostics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area-environmentEnvironment, interpreter related issues.bugIssue identified by VS Code Team member as probable buginfo-neededIssue requires more information from postertriage-needed

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions