microsoft / microsoft/vscode

"getWslProfiles" blocks main thread via synchronous "CreateProcessW"

Open
#326,670 2 comments 0 reactions 1 assignee Claimed by @meganrogge View on GitHub
confirmation-pending terminal
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

Does this issue occur when all extensions are disabled?: Yes

- VS Code Version: 1.107.1
- OS Version: Windows 10/11 (x64) with WSL installed

## Bug Description

`getWslProfiles()` in `src/vs/platform/terminal/node/terminalProfiles.ts` calls `cp.exec("wsl.exe -l -q")` synchronously on the main thread (CrBrowserMain / Node.js event loop). On Windows, `uv_spawn` → `CreateProcessW` → `NtCreateUserProcess` is a **blocking kernel call** that can stall the main thread for **100ms to 6+ seconds**, causing full UI freeze.

## Root Cause

The `cp.exec("wsl.exe -l -q")` call in `getWslProfiles` (terminalProfiles.ts:347-358) executes on the main thread. On Windows, libuv's `uv_spawn` invokes `CreateProcessW` which is a synchronous kernel call — the `timeout: 1000` option only limits stdout wait time, **not** the process creation itself.

`wsl.exe` is particularly slow to spawn because:
1. WSL subsystem cold-start may require launching a lightweight VM / Hyper-V instance
2. Antivirus software (Windows Defender, etc.) hooks and scans `CreateProcess`
3. Kernel resource contention under high system load

## Call Stack (native + JS, sourcemap-resolved)
- native call stack
[crash_stack (1).txt](https://github.com/user-attachments/files/30196545/crash_stack.1.txt)
- node js call stack
```
at getWslProfiles (lib/vscode/src/vs/platform/terminal/node/terminalProfiles.ts:151:24)
const result = await getWslProfiles(`${system32Path}\\wsl.exe`, defaultProfileName);
at ube (lib/vscode/src/vs/platform/terminal/node/terminalProfiles.ts:349:28)
const distroOutput = await new Promise((resolve, reject) =>
at new Promise ()
at r (lib/vscode/src/vs/platform/terminal/node/terminalProfiles.ts:352:5)
cp.exec('wsl.exe -l -q', { encoding: 'utf16le', env: { ...process.env, WSL_UTF8: '0' }, timeout: 1000 }, (err, stdout) =>
at Module.exec (node:child_process:236:25)
at t. [as execFile] (node:electron/js2c/node_init:2:3013)
at Object.execFile (node:child_process:349:17)
at spawn (node:child_process:801:9)
at ChildProcess.spawn (node:internal/child_process:422:13)
at process.nextTick (node:electron/js2c/browser_init:2:149394)
```

## Steps to Reproduce

1. Use VS Code on Windows with WSL installed (especially with multiple distros).
2. Open VS Code — terminal profile detection runs automatically on startup.
3. Open the terminal dropdown or create a new terminal instance.
4. Observe UI freeze/jank for 100ms~seconds while `wsl.exe -l -q` spawns.
5. Reproduction is more reliable when: WSL has not been used recently (cold start), antivirus is active, or system is under load.

## Expected Behavior

Terminal profile detection should not block the main thread. The UI should remain responsive during WSL profile enumeration.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.