谨慎同时使用WSLG和GWSL

GWSL是在WSLg诞生之前用于为WSL2提供图形化支持的方案之一,但是其部分功能会破坏WSLg依赖的环境变量,从而使其无法正常工作

WSLg提供了GWSL的大部分功能。除非需要在WSLg中运行OpenGL应用(issue),否则大部分时候考虑只使用WSLg即可。

0x00 起因

最近在折腾WSL下用QEMU开黑苹果以开发iOS软件,结果QEMU一直起不来,报错如下:

1
2
3
pulseaudio: Wrong context state
pulseaudio: Reason: Connection refused
pulseaudio: Failed to initialize PA contextqemu-system-x86_64: could not connect to PulseAudio server

但是我用musicbox测试了音频,发现音频工作正常,而且老早之前还用QEMU起过kali虚拟机,当时音频也做了额外配置但是忘记了。这回无论如何都不能工作,遂开始分析原因。

0x01 分析

老早之前我通过环境变量修复了这个问题,是如下脚本(已废弃):

1
2
3
alias fixWayland="ln -s /mnt/wslg/runtime-dir/wayland-0* /run/user/$(id -u)/"
alias fixPulse="mkdir /run/user/$(id -u)/pulse; ln -s /mnt/wslg/runtime-dir/pulse/native /run/user/$(id -u)/pulse/native; ln -s /mnt/wslg/runtime-dir/pulse/pid /run/user/$(id -u)/pulse/pid"
alias fixWSLG="fixWayland; fixPulse"

这段代码配合在WSL内再手动起一个pulseaudio的服务,可以暂时解决问题(启动QEMU),只是不能播放音频。这个方案在今晚却失效了,于是不得不开始寻找问题的根源。

通过搜索,查到Github上的一个issue。这大概是反馈QEMU无法初始化pa(直通)的问题,里面提到:QEMU PulseAudio seems to work and initializes only if the pulseaudio server was explicitly started and enabled auth-anonymous in either unix or tcp mode, without enabling auth-anonymous it would fail to utilize it.

也就是说,QEMU依然依赖本地的pulseaudio server。于是,我开始检查$PULSE_SERVER环境变量,却发现它惊人地指向了tcp:10.255.255.254。这是一个很奇怪的IP,看格式像是一个网关,而且能ping通。$DISPLAY变量也指向了10.255.255.254:0.0。根据WSLg的文档,这种配置下GUI是能正常工作的,但是音频应该不能,后者应该要通过一个unix socket连接unix:/mnt/wslg/PulseServer

我想起来这应该是由于设置了dnsTunneling=true时候WSL2会把DNS请求转发到Windows,应该就是/etc/resolv.conf的设置。不过,也有可能是WSLg把pulseaudio的功能转交给Windows而主动设置的环境变量,因而这也合理。

于是我关闭了dnsTunneling,发现这个变量指向了我的本机IP。于是确认了这个变量随着/etc/resolv.conf变化。这其实是GWSL的一个自动化功能(如下代码),在WSLg之前能提供无感使用图形界面的体验。然而现在这使得音频无法正常工作。关键是我记得在之前我手动在~/.bashrc内删除了这两行,理论上应该不会再自动导出这两个变量了。我检查了~/.profile/etc/profile,但是仍然找不到是在哪导出的。

1
2
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}'):0.0 #GWSL
export PULSE_SERVER=tcp:$(cat /etc/resolv.conf | grep nameserver | awk '{print $2; exit;}') #GWSL

于是把GWSL打开,看有没有办法让它去清理环境变量。最后在GWSL Distro Tools/More Shells and Options中找到了Clean GWSL Additions才完成清理。再次检查两个变量得到:

1
2
3
4
> echo $PULSE_SERVER
unix:/mnt/wslg/PulseServer
> echo $DISPLAY
:0

此时重启WSL,pulseaudio服务会正常工作(但是默认情况只有non-root用户才有,QEMU因此也得运行在non-root模式下),QEMU能正常启动。

0x02 结论

GWSL自动导出$DISPLAY$PULSE_SERVER环境变量的设置会使得WSLg无法正常工作。对于从GWSL迁移到WSLg的用户,应该考虑清理之前的环境变量。

Licensed under CC BY-NC-SA 4.0
Last updated on Mar 09, 2025 22:41 CST
Total Page View: Loading  Total Visits: Loading  Site Total Visitors: Loading
京ICP备2024091870号-1
Built with Hugo
Theme Stack designed by Jimmy