Skip to content

Session relay's vsock accept has no timeout; orphaned relays never exit, pinning vmbus rings until new sessions fail #41242

Closed

Description

@Wizard1209

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:

  1. Run a session-heavy workload for days.
  2. ps -e -o pid,ppid,comm | awk '$3=="Relay"' — live relays are named Relay(<childpid>), stuck ones stay exactly Relay.
  3. 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 accept every ~30 s.
  4. Eventually new sessions hang (wsl.exe -e echo ok times out) while existing sessions and wsl --list --running still 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:

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

  1. github-actions commented on Aug 4, 2026

    @github-actions
    Contributor

    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:

    Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/collect-wsl-logs.ps1" -OutFile collect-wsl-logs.ps1
    Set-ExecutionPolicy Bypass -Scope Process -Force
    .\collect-wsl-logs.ps1
    

    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 networking instead, following the instructions in Collect WSL logs for networking issues

    Once 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'.

  2. Wizard1209 commented on Aug 5, 2026

    @Wizard1209
    Author

    Logs attached. Heads up on what they show: the archive is from the current, healthy boot — the wedge was cleared by wsl --shutdown and 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 bare Relay — SIGTERM sent and ignored, plus a precise census of the stuck relays, in one log. The 12 live Relay(<childpid>) of running sessions were killed alongside them.

    WslLogs-2026-08-04_18-45-49.tar.gz
    guest-journal-wedge-excerpt.txt

  3. github-actions commented on Aug 5, 2026

    @github-actions
    Contributor
    Diagnostic information
    .wslconfig found
    Detected appx version: 2.6.3.0
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions