Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Launching Win32 applications from within WSL #1243

Closed
jasonNXP opened this issue Oct 21, 2016 · 13 comments
Closed

Launching Win32 applications from within WSL #1243

jasonNXP opened this issue Oct 21, 2016 · 13 comments
Labels

Comments

@jasonNXP
Copy link

Description:

Unable to invoke application with spaces in directory name

Expected results:

Assume it should invoke the application properly.

Windows build number:

14951

Steps / All commands required to reproduce the error from a brand new installation:

cmd.exe /c /mnt/c/Program\ Files/Sublime\ Text\ 3/sublime_text.exe
The system cannot find the path specified.

Strace of the failing command

strace cmd.exe /c /mnt/c/Program\ Files/Sublime\ Text\ 3/sublime_text.exe
execve("/mnt/c/Windows/System32/cmd.exe", ["cmd.exe", "/c", "/mnt/c/Program Files/Sublime Tex"...], [/* 16 vars */]) = 0
brk(NULL) = 0x7fffd4434000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2918290000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=54002, ...}) = 0
mmap(NULL, 54002, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2918282000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1864888, ...}) = 0
mmap(NULL, 3967488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f2917c30000
mprotect(0x7f2917df0000, 2093056, PROT_NONE) = 0
mmap(0x7f2917fef000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bf000) = 0x7f2917fef000
mmap(0x7f2917ff5000, 14848, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f2917ff5000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2918280000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2918270000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2918260000
arch_prctl(ARCH_SET_FS, 0x7f2918270700) = 0
mprotect(0x7f2917fef000, 16384, PROT_READ) = 0
mprotect(0x7f2918609000, 4096, PROT_READ) = 0
mprotect(0x7f2918225000, 4096, PROT_READ) = 0
munmap(0x7f2918282000, 54002) = 0
getpid() = 77
getcwd("/home/public", 4096) = 13
open("/dev/lxssclient", O_RDWR) = 3
ioctl(3, _IOC(0, 0x00, 0x2f, 0x22), 0x7fffdcbe31b0) = 0
brk(NULL) = 0x7fffd4434000
brk(0x7fffd4455000) = 0x7fffd4455000
ioctl(3, _IOC(0, 0x00, 0x3f, 0x22), 0x7fffdcbe3038) = 0
ioctl(3, _IOC(0, 0x00, 0x3f, 0x22), 0x7fffdcbe3038) = -1 EINVAL (Invalid argument)
ioctl(4, _IOC(0, 0x00, 0x97, 0x22), 0x7fffdcbe30f8) = 0
ioctl(4, _IOC(0, 0x00, 0xb7, 0x22), 0x7fffdcbe30f0) = 0
ioctl(4, _IOC(0, 0x00, 0xb7, 0x22), 0x7fffdcbe30f0) = 0
ioctl(4, _IOC(0, 0x00, 0xb7, 0x22), 0x7fffdcbe30f0) = 0
write(4, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 197) = 197
read(4, "3\0\0\0\0\0\0\0", 8) = 8
ioctl(4, _IOC(0, 0x00, 0x9b, 0x22), 0x7fffdcbe31a8) = 0
write(4, "3\0\0\0\0\0\0\0", 8) = 8
ioctl(5, _IOC(0, 0x00, 0xbf, 0x22)The system cannot find the path specified.
, 0x7fffdcbe3198) = 0
close(3) = 0
close(4) = 0
close(5) = 0
exit_group(1) = ?
+++ exited with 1 +++

Required packages and commands to install

Any Windows application with spaces in the directory name

@benhillis
Copy link
Member

benhillis commented Oct 21, 2016

What if you invoke sublime_text.exe directly? I think the issue is that you are passing a Linux path to cmd.exe. We don't do any translation of command line arguments.

@jasonNXP
Copy link
Author

Yes, I'm able to invoke the executable directly from the parent folder and it will launch properly.

I'm able to work around this by adding the "C:\Program Files\Sublime Text 3" folder to my path and run sublime_text.exe directly.

@benhillis
Copy link
Member

@jasonNXP Thanks for confirming.

@fpqc
Copy link

fpqc commented Oct 23, 2016

@benhillis I know this is a problem without a straightforward answer, but is it something you're looking into? It seems like the main problems would show up if you had a collision between a translated path and a Windows executable flag argument.

One possibility is maybe to try to assume it's a path, see if it resolves to a file referenced through /mnt, and if it does, translate the path. Otherwise, pass it as an argument instead? It seems like the edge cases are probably few and far between.

Another way might be to change the way the interpreter works, so that passing Windows executable flag arguments need to be specified by launching with a linux-style flag argument so that to launch

cmd.exe /c, you would do cmd.exe -f /c or the other way around where -f could specify a Linux-style path. Not sure how flexible the system is.

@aseering
Copy link
Contributor

aseering commented Oct 23, 2016

Does anyone know how Cygwin solves this problem? (Specifically, what rules they use for path translation.) As I recall, they attempt to do so, and their attempt works pretty well.

@fpqc
Copy link

fpqc commented Oct 23, 2016

@aseering I have cygwin installed, and I don't understand how it works actually...

It seems highly inconsistent.

I'm in my cygwin home, and here's how it goes:

mkdir test1
touch test1/test1
xcopy test1 test2

This test quickly explodes and starts outputting what appear to be strange garbage characters after I tell it that test2 should be a directory, not so good.

Then when I try to do it with xcopy ./test1 ./test2 I get something telling me I don't have enough params.

The reason probably why you are thinking it works alright is that cygwin seems to alias dir and dir.exe (which doesn't even exist) to cygwin's ls.exe, which interprets cygwin paths in the usual way.

@benhillis
Copy link
Member

"Magically" converting paths on the command line was considered but I was concerned with converting something that was not really a path because it looked like one.

Relative paths don't need to be converted since NT handles / and \ interchangeably - so this only effects specifying an absolute path.

I'll run this by the team next week and see what people think.

@fpqc
Copy link

fpqc commented Oct 23, 2016

@benhillis Yeah, I am aware that this particular magic is hard, given how notoriously "un-robust" bash is at handling of character escapes.

@xilun
Copy link

xilun commented Oct 23, 2016

Relative paths sometimes need to be converted because some programs do not just forward their args to NT as a file to open, but interpret them directly, in which case everybody uses its own rules. However, it might cause more damages than good, given every Win32 program can parse its own command line and add its own special parsing rules, sometimes completely crazy (cmd.exe, I'm looking at you :)

I think absolute path starting with /mnt/ should be safe enough and helpful to convert.

The next problem is Win32 command line parameter escaping. Here the fact that it is done by the called program potentially using custom methods hits again badly, because you basically wants to escape according to CommandLineToArgvW / crt rules (which are probably the most commonly used), except that it won't work well for cmd.exe (which is a non-negligeable use case) - and interestingly also for bash.exe :P ... No perfect solution for that either I guess.

@aseering
Copy link
Contributor

Question for Windows folks (my background is more in Linux) -- can "/mnt/c" ever be a valid Windows path prefix?

If not, one solution in principle (admittedly with various potential downsides) would be to make the regular Windows APIs treat it as an alias for "C:". Then, at least programs that pass the path through without trying too hard to parse it will succeed.

@fpqc
Copy link

fpqc commented Oct 23, 2016

@aseering Windows has at least 3 absolute path conventions, and this should conflict with none of them, it seems.

@benhillis
Copy link
Member

@aseering, @fpqc A simple string-based solution will only work in the base case where entire drives are mounted under /mnt/. In the future we may allow arbitrarily mounting NTFS folders or volumes or mounting to places other than /mnt/. In that case the driver will need to be consulted to return the correct Windows path.

I have some ideas for an approach that world work long-term, but my main concern is still with false positives. The problem is that cases where Windows apps implement their own "strange" argument parsing. Let's say app Foo.exe has a command line argument "/mnt/c". The binfmt interpreter is going to assume that's a path and convert it to C:\ and pass that to Foo.exe which may not be a valid argument. Kind of a contrived example, but that's the type of thing we're concerned with. I suppose if we make it a configurable behavior that takes away some of the risk.

@Brian-Perkins
Copy link

Windows Insider Build 17046 contains new 'wslpath' functionality that supports path translations. See the release notes for more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants