Skip to content

WSL2 rtnl deadlock after hv_netvsc sub-channel open fails with ENOMEM #41474

Description

@fiberproduct

Windows Version

10.0.26200.8037

WSL Version

2.7.12.0

Are you using WSL 1 or WSL 2?

  • WSL 2
  • WSL 1

Kernel Version

6.18.33.2-2 (uname -r: 6.18.33.2-microsoft-standard-WSL2)

Distro Version

Ubuntu 24.04.4 LTS

Other Software

  • .wslconfig at time of incident: memory=2560MB, processors=4, swap=2GB,
    autoMemoryReclaim=gradual (host has 8 GB RAM; limit since raised to 4096MB)
  • Inside the VM: long-lived opencode CLI (Bun runtime) session ~735 MB RSS
    plus several ~150 MB child processes — the source of memory pressure

Repro Steps

Cannot reproduce on demand — it requires kernel memory exhaustion inside a
small VM. Single occurrence on 2026-08-28 ~05:30 UTC with full capture below.

Trigger profile:

  1. Set .wslconfig memory cap well below steady-state process usage
    (2560 MB cap vs ~1.3 GB of resident processes + page cache).
  2. Let memory pressure reach kernel OOM conditions (dmesg shows allocation
    failure reports from vmbus channel-open work).
  3. From that moment, every process that calls getifaddrs() at startup
    (Node/Bun runtimes, ip addr, ...) hangs forever in D state — each
    retry adds another unkillable process, worsening the exhaustion.

Expected Behavior

A failed sub-channel open (ENOMEM) should unwind, release rtnl, and let the
interface keep working single-channel. Netlink queries must not be able to
wedge the whole control plane permanently, and the VM must remain
shut-downable (wsl --shutdown should not hang).

Actual Behavior

Under kernel memory pressure, the network stack wedged permanently:

  1. Every process calling getifaddrs() hung forever in D state,
    wchan = rtnl_dumpit; SIGKILL undeliverable.
  2. One child became an unreapable zombie.
  3. wsl --shutdown itself hung indefinitely (graceful shutdown waits for
    processes to exit).
  4. Only recovery: elevated taskkill /F on vmmemWSL.exe and wslservice.exe
    (service stuck in STOP_PENDING), then restart vmcompute + WSLService.

Notably, established connections / data-plane traffic kept working — only
netlink control/query paths hung, consistent with rtnl_mutex being held
forever while data paths use RCU.

Analysis: sub-channel open (netvsc_sc_open → vmbus_open) failed with -ENOMEM
while rtnl was held, and the error path appears to never release rtnl_mutex.
From that point every RTM_GETLINK netlink dump blocks forever — exactly where
the D-state processes were stuck (rtnl_dumpit).

Diagnostic Logs

Captured from dmesg while the wedge was live (the VM was later force-killed,
so this capture is the primary evidence):

hv_netvsc de1108d5-...  eth0: sub channel open failed: -12
hv_netvsc de1108d5-...  eth0: sub channel open failed: -12

with kernel stack trace:

__vmbus_open → vmbus_open → netvsc_sc_open → vmbus_add_channel_work
? rtnl_is_locked+0x19/0x30

followed by a full kernel allocation-failure report (Mem-Info dump) and:

WSL (107) ERROR: CheckConnection: getaddrinfo() failed: -5
warn_alloc: 1 callbacks suppressed

Related:

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