Skip to content

Commit 28185e3

Browse files
committed
interop: enable preserveArgvZero
Fixes interop with latest WSL versions
1 parent 80c18db commit 28185e3

File tree

1 file changed

+46
-5
lines changed

1 file changed

+46
-5
lines changed

modules/wsl-distro.nix

+46-5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ with builtins; with lib;
4242
description = "Include Windows PATH in WSL PATH";
4343
};
4444
};
45+
46+
compatibility = {
47+
interopPreserveArgvZero = mkOption {
48+
type = nullOr bool;
49+
default = null;
50+
description = ''
51+
Register binfmt interpreter for Windows executables with 'preserves argv[0]' flag.
52+
53+
Default (null): autodetect, at some performance cost.
54+
To avoid the performance cost, set this to true for WSL Preview 0.58 and up,
55+
or to false for older versions (including pre-Microsoft Store).
56+
'';
57+
};
58+
};
4559
};
4660

4761
config =
@@ -65,11 +79,38 @@ with builtins; with lib;
6579
isContainer = true;
6680

6781
binfmt.registrations = mkIf cfg.interop.register {
68-
WSLInterop = {
69-
magicOrExtension = "MZ";
70-
interpreter = "/init";
71-
fixBinary = true;
72-
};
82+
WSLInterop =
83+
let
84+
compat = cfg.compatibility.interopPreserveArgvZero;
85+
86+
# WSL Preview 0.58 and up registers the /init binfmt interp for Windows executable
87+
# with the "preserve argv[0]" flag, so if you run `./foo.exe`, the interp gets invoked
88+
# as `/init foo.exe ./foo.exe`.
89+
# argv[0] --^ ^-- actual path
90+
#
91+
# Older versions expect to be called without the argv[0] bit, simply as `/init ./foo.exe`.
92+
#
93+
# We detect that by running `/init /known-not-existing-path.exe` and checking the exit code:
94+
# the new style interp expects at least two arguments, so exits with exit code 1,
95+
# presumably meaning "parsing error"; the old style interp attempts to actually run
96+
# the executable, fails to find it, and exits with 255.
97+
compatWrapper = pkgs.writeShellScript "nixos-wsl-binfmt-hack" ''
98+
/init /nixos-wsl-does-not-exist.exe
99+
[ $? -eq 255 ] && shift
100+
exec /init $@
101+
'';
102+
103+
# use the autodetect hack if unset, otherwise call /init directly
104+
interpreter = if compat == null then compatWrapper else "/init";
105+
106+
# enable for the wrapper and autodetect hack
107+
preserveArgvZero = if compat == false then false else true;
108+
in
109+
{
110+
magicOrExtension = "MZ";
111+
fixBinary = true;
112+
inherit interpreter preserveArgvZero;
113+
};
73114
};
74115
};
75116
environment.noXlibs = lib.mkForce false; # override xlibs not being installed (due to isContainer) to enable the use of GUI apps

0 commit comments

Comments
 (0)