Skip to content

Commit

Permalink
fix: Bind mount /tmp/.X11-unix for newer version of WSL2 (#57)
Browse files Browse the repository at this point in the history
Fix #56.

After WSL 0.60.0 release, microsoft switched to bind mount the /tmp/.X11-unix rather than symlink it as they previously do. This breaks wslg in Distrod for latest WSL on MS Store.

Distrod should bind mount for WSL 0.60.0, and keep the symlink strategy for older versions of WSL.
  • Loading branch information
Locietta committed Jul 7, 2022
1 parent 4320147 commit 921bc3c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 11 deletions.
24 changes: 13 additions & 11 deletions distrod/distrod/tests/integration_test.rs
Expand Up @@ -326,17 +326,19 @@ fn test_wslg_socket_is_available() {
// Wait for a while until Systemd initializes /tmp
std::thread::sleep(Duration::from_secs(15));

let mut test = DISTROD_SETUP.new_command();
test.args(&["exec", "--", "test", "-e", "/run/tmpfiles.d/x11.conf"]);
let child = test.status().unwrap();
assert!(child.success());

let mut ls = DISTROD_SETUP.new_command();
ls.args(&["exec", "--", "ls", "-ld", "/tmp/.X11-unix"]);
let output = ls.output().unwrap();
let output = String::from_utf8_lossy(&output.stdout);
eprintln!("output of `ls -ld /tmp/.X11-unix`: {}", output);
assert!(output.ends_with("-> /mnt/wslg/.X11-unix\n"));
// WSL prior to version 0.60.0 creates `/mnt/wslg/.X11-unix`,
// so distrod will create a symbolic link to it in `/tmp/.X11-unix` using `tmpfiles.d`.
let mut test_wsl_before_0_60_0 = DISTROD_SETUP.new_command();
test_wsl_before_0_60_0.args(&["exec", "--", "test", "-e", "/run/tmpfiles.d/x11.conf"]);
let result_old = test_wsl_before_0_60_0.status().unwrap();

// WSL bind-mounts `/tmp/.x11-unix` since 0.60.0.
// Check `systemd-tmpfiles-setup.service.d` has the config to prevent systemd from cleaning it up.
let mut test_new = DISTROD_SETUP.new_command();
test_new.args(&["exec", "--", "test", "-e", "/run/systemd/system/systemd-tmpfiles-setup.service.d/exclude_wslg_sockets.conf"]);
let result_new = test_new.status().unwrap();

assert!(result_old.success() || result_new.success());
}

#[test]
Expand Down
39 changes: 39 additions & 0 deletions distrod/libs/src/distro.rs
Expand Up @@ -52,6 +52,12 @@ impl DistroLauncher {
.with_context(|| "Failed to mount /run files.")?;
prepend_distrod_bin_to_path(&mut distro_launcher)
.with_context(|| "Failed to set the distrod bin dir in PATH.")?;

if is_wsl_bind_mount_dotx11_unix().unwrap() {
mount_dotx11_unix_for_wslg(&mut distro_launcher)
.with_context(|| "Failed to mount /tmp/.X11-unix for wslg")?;
}

Ok(distro_launcher)
}

Expand Down Expand Up @@ -255,6 +261,27 @@ fn mount_kernelcmdline_with_wsl_interop_envs_for_systemd(
Ok(())
}

const X11_TARGET_PATH: &str = "/tmp/.X11-unix";
const WSLG_PATH: &str = "/mnt/wslg/.X11-unix";

fn is_wsl_bind_mount_dotx11_unix() -> Result<bool> {
// if it's an existing dir, then it's WSL>=0.60.0, we should bind-mount it
// otherwise, it's some older versions, waiting a symlink to be created later
Ok(Path::new(X11_TARGET_PATH).is_dir() && Path::new(WSLG_PATH).exists())
}

fn mount_dotx11_unix_for_wslg(distro_launcher: &mut DistroLauncher) -> Result<()> {
distro_launcher.with_mount(
Some(HostPath::new(WSLG_PATH)?),
ContainerPath::new(X11_TARGET_PATH)?,
None,
nix::mount::MsFlags::MS_BIND,
None,
false,
);
Ok(())
}

fn get_cmdline_with_wsl_interop_envs_for_systemd<P: AsRef<Path>>(
cmdline_path: P,
) -> Result<Vec<u8>> {
Expand Down Expand Up @@ -374,6 +401,18 @@ fn mount_slash_run_static_files(distro_launcher: &mut DistroLauncher) -> Result<
if !path.is_file() {
continue;
}

// don't mount `x11.conf` for wsl>=0.60.0
if is_wsl_bind_mount_dotx11_unix().unwrap()
&& path
== Path::new(&format!(
"{}/tmpfiles.d/x11.conf",
distrod_config::get_distrod_run_overlay_dir()
))
{
continue;
}

let dest_mount_path = ContainerPath::new(
Path::new("/run").join(
path.strip_prefix(distrod_config::get_distrod_run_overlay_dir())
Expand Down
@@ -0,0 +1,10 @@
# This file is part of Distrod.
#
# Do not edit this file directly. This file can be overwritten when Distrod is updated.
# Instead, create /etc/systemd/system/systemd-tmpfiles-clean.service.d/exclude_wslg_sockets.conf,
# systemd will load it.

# avoid `/tmp/.X11-unix` to be cleaned up by systemd
[Service]
ExecStart=
ExecStart=systemd-tmpfiles --clean --exclude-prefix=/tmp/.X11-unix
@@ -0,0 +1,10 @@
# This file is part of Distrod.
#
# Do not edit this file directly. This file can be overwritten when Distrod is updated.
# Instead, create /etc/systemd/system/systemd-tmpfiles-setup.service.d/exclude_wslg_sockets.conf,
# systemd will load it.

# avoid `/tmp/.X11-unix` to be cleaned up by systemd
[Service]
ExecStart=
ExecStart=systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev --exclude-prefix=/tmp/.X11-unix

0 comments on commit 921bc3c

Please sign in to comment.