Launch GUI applications in WSL with Unix Domain Socket
-
Install patched VcXsrv (Windows port of X-Org server) on Windows. Launch it with
-listen unix
. -
Install patched libxcb on WSL.
-
Create symlink:
/tmp/.X11-unix
->/mnt/c/tmp/.X11-unix
. -
To test, run
DISPLAY=unix:0 gnome-terminal
in WSL.
-
Install patched PulseAudio server on Windows. Launch it with module
module-native-protocol-unix socket=C:\\tmp\\pulse\\pulse.sock auth-anonymous=1
. -
Install patched libpulse on WSL.
-
To test, run
PULSE_SERVER=/mnt/c/tmp/pulse/pulse.sock paplay -p /mnt/c/Windows/media/ding.wav
Running a desktop environment or a GUI application in Windows Subsystem of Linux has not been not a suprise for a long time. In short, for a GUI application on Linux, to show graphics, it connects to a X-Org
server through X11
protocol, and to play sounds, it connects to a PulseAudio
server. That is how it works on traditional Linux environment, and thanks to its network transparncy, we are able to use the same stack on Windows.
We usually use Unix Domain Socket (AF_UNIX) on Linux to communicate with graphics and audio servers. However, all of the existing solutions to run GUI applications in WSL utilize TCP loopback (TCP connection to 127.0.0.1
) instead of Unix Domain Socket.
Windows 10 supports AF_UNIX since 1803, and even better this implementation supports interop between Windows and WSL. Therefore, it is totally possible to let the Windows port of X-Org
server and PulseAudio
server support Unix Domain Socket. So I did it, and here is the instruction.
My patch for X-Org
is based on VcXsrv
, one of the Windows port of X-Org
(I would say it is a fork of XWin
, just like others). You can download a compiled release here:
Once it gets installed, you can launch an X-Org
server by the following command:
.\vcxsrv.exe -nolisten tcp -listen unix -multiwindow
This will start the server at display port 0
. Then you can verify whether it works by right click its icon in the task bar, choose Applications
and launch xcalc
. You will see a calculatator window if everything works as expected.
Unfortunately you cannot specify the socket path for it, because you are not able to do so neither on Linux. The socket path is hard coded as /tmp/.X11-unix/X#
where #
is the display port. On Windows this will be converted to C:\tmp\X11-unix\X#
.
You can download a compiled release with my patch here:
There is no installer for it so just unzip it to a place you like. Then you need to modify its launch script to enable Unix Domain Socket. The default launch script is .\etc\default.pa
. Alternatively you can copy it to ~\.config\pulse\default.pa
. Add the following line in the network access section (you may change the socket path to anywhere you like, but must on NTFS and not in WSL):
load-module module-native-protocol-unix socket=C:\\tmp\\pulse\\pulse.sock auth-anonymous=1
Then you can launch a PulseAudio
server by the following command:
.\pulseaudio.exe
To verify your setup, use paplay
:
.\paplay -s unix:C:\tmp\pulse\pulse.sock -p C:\Windows\media\ding.wav
You will hear DING if everything works as expected.
There is not supposed to be patches in WSL. However currently there is a limitation of Unix Domain Socket interop between Windows and WSL: socket()
must be followed by bind()
or connect()
. No other syscalls should be between them. Otherwise the socket will become WSL internal only. So I removed couple of lines in libxcb and libpulse.
You can follow the instructions in the release page to install it:
Then you need to create a symlink to point /tmp/.X11-unix
to the actual socket path directory in the C drive:
sudo ln -s /mnt/c/tmp/.X11-unix /tmp/
Double check:
ls -l /tmp/.X11-unix
Verification (launch VcXsrv
first):
DISPLAY=unix:0 gnome-terminal
You can follow the instructions in the release page to install it:
Verification (launch PulseAudio
first):
PULSE_SERVER=unix:/mnt/c/tmp/pulse/pulse.sock paplay -p /mnt/c/Windows/media/ding.wav
Does Unix Domain Socket perform better than TCP loopback?
- Likely. I tried to play a YouTube video in 2K resolution on my MacBook Air. The content of the video was roller coaster whose image changed rapidly, so that the throughput of X11 maximized, and I was able to check tearing. I saw about 20% drop of CPU utilization by switching to AF_UNIX. But I need more formal experiment to support this conclusion.
Can I use it in WSL2?
- No, not now. The first release of WSL2 won't support AF_UNIX interop as I know so far. They might change their mind before release.
I don't trust your binary release
- Just cherry-pick my feature branch and build by yourself.