init aborts (SIGABRT) when an interop client disconnects before its reply: wil::ResultException Broken pipe inside wil::scope_exit in the Interop thread
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 33.7k
- Forks
- 1.8k
- Avg merge
- 3d 17h
- Merged PRs (30d)
- 116
Description
Environment
- WSL 2.7.11.0, kernel 6.18.33.2-microsoft-standard-WSL2, WSLg 1.0.73.2
- Windows 10.0.26200.9445
- Ubuntu distro with
[boot] systemd=true
What happens
The distro's init (init-systemd(Ubuntu), PID 2 inside the pid namespace) dies with SIGABRT. Afterwards every new wsl.exe -d Ubuntu session fails immediately with Wsl/Service/E_UNEXPECTED, interop calls from inside the distro hang, VS Code Remote loops on reconnect; systemd inside the distro keeps running. Only wsl --terminate Ubuntu recovers.
Three occurrences in 24 hours, identical crash dumps (%LOCALAPPDATA%\Temp\wsl-crashes\wsl-crash-*-2-_init-6.dmp, "pid: 2, executable: !init, signal: 6"). dmesg each time:
WSL (2 - Interop) ERROR: SendMessage:182: Failed to write message LxMessageResultBool. Channel: InteropServer
libc++abi:
terminating due to uncaught exception of type wil::ResultException: Broken pipe @C:/__w/1/s/src/shared/inc\SocketChannel.h:183 (SendMessage)
init: Interop: potentially unexpected fatal signal 6.
WSL (8531 - CaptureCrash): Capturing crash for pid: 2, executable: !init, signal: 6, port: 50005
One of the three additionally logged, right before the abort:
WSL (2 - Interop) ERROR: CreateLoginSession:2758: Timed out waiting for user session for uid=0
Where in the source (main as of 2026-09-11, eaa69e7)
src/linux/init/config.cpp, ConfigHandleInteropMessage, case LxInitMessageCreateLoginSession:
bool success = false;
auto sendResponse = wil::scope_exit([&]() { Transaction.SendResultMessage<bool>(success); });
...
success = CreateLoginSession(Config, ..., CreateSession->Uid);
CreateLoginSession can block for up to boot.initTimeout (10 s default) polling systemctl is-active user@<uid>.service, on the single "Interop" worker thread. If the client (the session leader /init that wsl.exe started) has gone away meanwhile because the Windows-side caller timed out or was killed, SendResultMessage throws wil::ResultException (EPIPE). It throws from inside the wil::scope_exit lambda, whose destructor is noexcept, so the surrounding try { ... } CATCH_LOG() never sees it and std::terminate takes the whole init down.
The Interop thread is also single and unbounded: for (;;) { Accept; ReceiveTransaction; ReceiveOrClosed; handle } with no receive timeout, so one stalled client (in our case a process throttled by a cgroup memory.high limit) queues every other session start behind it, which is what makes callers give up and close their end.
Reproduction
wsl --terminate Ubuntu- Make the first root session slow, for example a systemd that needs more than 10 s to reach
user@0.service(we hadStartup finished in 18.6s), or any load that delays it. - From PowerShell:
$j = Start-Job { wsl -d Ubuntu -u root -e true }; Wait-Job $j -Timeout 3; Stop-Job $j - When
CreateLoginSessiontimes out (or merely finishes) and writes its bool result, init aborts and the distro is unusable until terminated.
Suggested fix
- Send the result inside the
trybody instead of from awil::scope_exit, or wrap the send in the lambda with aCATCH_LOG(); a client that hung up must not take init with it. - Ideally, bound
ReceiveTransaction/ReceiveOrClosedon the Interop server socket with a timeout, so one stalled client cannot block every other session start.
Mitigation we use meanwhile (for others hitting this)
loginctl enable-linger root (and for the default user), so user@<uid>.service is active before the first session and CreateLoginSession returns at once; keep systemd's boot under boot.initTimeout; never wrap wsl.exe -d ... in a kill-on-timeout.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/linux/init/config.cpp at ConfigHandleInteropMessage and its LxInitMessageCreateLoginSession case; inspect how the scope_exit sends the result after CreateLoginSession blocks. Reproduce with the slow-session and killed wsl.exe steps, then verify a disconnected client no longer aborts init. Also inspect the Interop server loop around Accept, ReceiveTransaction, and ReceiveOrClosed for the stalled-client behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- networking, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100