Repository navigation
Description
Windows Version
Microsoft Windows [Version 10.0.26200.7840]
WSL Version
2.6.3.0 (bug still present on master by inspection)
Are you using WSL 1 or WSL 2?
WSL 2
Kernel Version
6.6.87.2-1
Distro Version
Ubuntu 24.04
Other Software
Docker Desktop (WSL integration); agent-heavy workload — 5–15 concurrent sessions, frequent short wsl.exe -e calls
Repro Steps
No deterministic repro — the trigger is wslservice's per-session hvsocket connects partially failing (#40650 traced that to WSAENOBUFS on the Windows side). But the defect that turns a transient failure into a permanent leak is visible in the source, and easy to observe on any long-lived session-heavy machine:
- Run a session-heavy workload for days.
ps -e -o pid,ppid,comm | awk '$3=="Relay"'— live relays are namedRelay(<childpid>), stuck ones stay exactlyRelay.- Watch the count grow (ours: 2 → 37 → 62 → 44 distinct per day, 131 total over 6 days), each stuck relay logging
UtilAcceptVsock:244: Waiting for abnormally long acceptevery ~30 s. - Eventually new sessions hang (
wsl.exe -e echo oktimes out) while existing sessions andwsl --list --runningstill work — the accept4 failed 110 on new WSL sessions when vsock connection count is high — no tunable limit exists #40650 / New WSL sessions hang under memory pressure with vmbus_alloc_ring allocation failure #40795 end state.
Expected Behavior
Relay accept is bounded — precedent exists, the session-leader accept path passes SESSION_LEADER_ACCEPT_TIMEOUT_MS (30 s, common.h) and fails fast with accept4 failed 110. And a relay whose session leader died exits: there's nothing left to relay.
Actual Behavior
In CreateProcessUtilityVm (init.cpp ~1451 on tag 2.6.3, ~1481 on master) the relay thread calls UtilAcceptVsock(ListenSocket, SocketAddress) with no timeout → default Timeout = -1 (util.h) → the poll loop in util.cpp retries forever. If wslservice completes only some of the session's LX_INIT_UTILITY_VM_CREATE_PROCESS_SOCKET_COUNT connects, the relay blocks there indefinitely:
- never exits, even long after its session leader is dead;
- ignores SIGTERM (
SigIgn: fffffffc7ff8fefe, per accept4 failed 110 on new WSL sessions when vsock connection count is high — no tunable limit exists #40650) — SIGKILL only; - keeps its accepted hv_sock channels open, and each channel pins an order-7 (512 KB physically contiguous)
vmbus_alloc_ringallocation (New WSL sessions hang under memory pressure with vmbus_alloc_ring allocation failure #40795). Enough stuck relays fragment guest memory until new channels can't allocate rings: new sessions fail, old ones work, and per the accept4 failed 110 on new WSL sessions when vsock connection count is high — no tunable limit exists #40650 field reportscompact_memorydoesn't recover it (rings are unmovable).
So a transient host-side connect failure compounds into a permanent guest-side leak.
Terminal stage on our machine: after ~6 days of accumulation the VM was cleanly shut down with processes still running (orderly systemd shutdown in the guest journal, no triggering event of any kind in the Windows System log) — all overnight work killed. Evidence in our #40650 comment.
Diagnostic Logs
Host-side ETW of the wslservice retry loop + guest journal data: #40650 (comment). More on request.
Workaround
The GC from #40650 (SIGKILL processes matching: cmdline /init, comm exactly Relay, no children, no /run/WSL/<pid>_interop, session leader dead, age > 10 min). One portability note: on a systemd distro orphaned relays reparent to pid 2 (the WSL /init), not pid 1 — the ppid check needs to accept both.
Related
#40650 (host-side trigger, no tunable limit), #40795 (memory mechanism), #41173 (interop busy-loop; sessions over sshd reportedly immune). Filing separately because the fix target differs: this is the guest-side lifecycle bug — unbounded accept, orphans never exiting — and it stays a bug even if the host-side limit gets raised.
Activity
github-actions commentedon Aug 4, 2026
Logs are required for review from WSL team
If this a feature request, please reply with '/feature'. If this is a question, reply with '/question'.
Otherwise, please attach logs by following the instructions below, your issue will not be reviewed unless they are added. These logs will help us understand what is going on in your machine.
How to collect WSL logs
Download and execute collect-wsl-logs.ps1 in an administrative powershell prompt:
The script will output the path of the log file once done.
If this is a networking issue, please use
.\collect-wsl-logs.ps1 -LogProfile networkinginstead, following the instructions in Collect WSL logs for networking issuesOnce completed please upload the output files to this GitHub issue.
See Collect WSL logs (recommended method).
If you choose to email these logs instead of attaching them to the bug, please send them to wsl-gh-logs@microsoft.com with the GitHub issue number in the subject, and include a link to your GitHub issue comment in the message body, and reply with '/emailed-logs'.
Wizard1209 commentedon Aug 5, 2026
Logs attached. Heads up on what they show: the archive is from the current, healthy boot — the wedge was cleared by
wsl --shutdownand the GC from #40650 is running here now, so this is the environment baseline, not the failure in progress. The failure-in-progress evidence (host-side ETW of the wslservice retry loop, guest error volume) is in my #40650 comment.Bonus from the wedged boot's journal (it survives reboots; excerpt attached): at the unprompted teardown systemd logged
init.scope: Stopping timed out. Killing.and then SIGKILLed exactly 100 processes named bareRelay— SIGTERM sent and ignored, plus a precise census of the stuck relays, in one log. The 12 liveRelay(<childpid>)of running sessions were killed alongside them.WslLogs-2026-08-04_18-45-49.tar.gz
guest-journal-wedge-excerpt.txt
github-actions commentedon Aug 5, 2026
Diagnostic information
fix(gate): retry windows-gate legs on the WSL vsock transport flake