-
Notifications
You must be signed in to change notification settings - Fork 20
Update Windows exe search order (phase 2) #358
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
Comments
For the status quo you wrote
but then for the proposal this becomes
That sounds like it's not the same thing? However, you're not discussing changing that part of the behavior either, so maybe this is meant to refer to the same thing in both cases? I am confused.
Oh, that may explain some extremely painful and confusing behavior I experienced on GHA recently. Having the system dirs overwrite PATH is certainly surprising and seems to be inconsistent both with Unix behavior and with the normal Windows behavior, so this is definitely something that should be changed.
It would be good to discuss where on the spectrum of "work like Unix" vs "work like normal Windows programs" this proposal lies. |
I've reworded to hopefully avoid confusion.
I've done a small edit to clarify that comment a bit and I'll attempt to expand upon the point later when I have time to write something more succinct. But here's the long version:
I'll repost the
The Unix behaviour is:
If
If
The suggested change simplifies this to always doing this:
Due to unifying the two behaviours, this leads to being slightly less Unix-like in the case where |
Thanks for the clarifications!
Is that what you called "the parent process' directory" above? I thought "the parent process' directory" referred to the current working directory, but "from which the application loaded" sounds more like the directory containing
Oh wow, so this is last normally on Windows? Seems like Windows users could be quite surprised then about Rust giving PATH a lot higher priority. Or maybe it's less "higher priority" and more "skipping the system directories". |
This is the directory in which the parent process executable resides, correct? Not the current working directory. I think the simplification you recommend sounds good. I presume we're allowed to deduplicate (2) and (3) when applicable? |
Yes, that's right. By "current directory" I meant the current working directory and by "application's directory" I meant the directory containing the application as given by
The system directories are in the And as noted, shells don't do that so there's already inconsistency. |
Sure but that's a libs optimization, rather than a libs-api question. |
Yeah seems to be quite the mess. From a Unix perspective, the most surprising part to me is "The directory from which the application loaded". I guess that's just a sufficiently common pattern on Windows that we have to support it? |
Yes, I believe so. Windows applications are generally packaged in their own directory rather than being in a soup of other applications. So, at least traditionally, giving high priority and trust to the application's load directory is expected. |
Note that on UNIX, |
Discussed in this week's meeting. We do want to drop searching the child's We had some discussions about whether to drop the application executable's directory. We'd like to understand whether there are any concerns about e.g. running applications directly in download directories. But it sounded like that should be considered separately with a close eye on compatibility, and with some understanding of what Windows already does in other contexts. |
@joshtriplett We do currently have a test that ensures the child's Removing that would mean that Windows deviates from other supported platforms. |
Fascinating. I don't think we were aware in the meeting that we search the child PATH on UNIX. Renominating for discussion. |
Ok, I refreshed my memory. I did looked into it a year ago so I had notes. The standard library manually sets the environment after forking and then uses That is surprising but very much intentional. It would have made things simpler for me if we didn't do that but here we are😆. |
Actually I opened a separate issue about documenting the behaviour of |
Should we provide an option for setting the search order? enum ExecutableSearchOrder {
System,
Consistent,
Custom(&[&Path]),
} |
Investigating that was an option I listed in "Alternatives" but:
|
This was discussed in the libs-api but there wasn't a lot of progress made. However the discussion did make me thing a better approach might be this:
This is easy enough to explain in documentation and it kinda matches the Unix behaviour in spirit if you squint a bit (i.e. does the native thing if you don't set It also should have a very limited effect. If someone really needs the old behaviour they can just append the application directory (and system directories if necessary) to the |
@ChrisDenton That would still break cases like "I added one utility directory to the PATH, and then ran a program that's found in the directory of my binary". |
rust-lang/rust#137673 fixed the bug with setting any environment variable on |
In the @rust-lang/libs-api meeting we decided to document the current behavior for now. rust-lang/rust#137673 solved the main issue that people were having, but we may want to re-visit this if people are still not happy with the new behavior. |
Proposal
Problem statement
On Windows, the
Command
program search uses slightly different rules depending on if the environment is inherited or not. To cut a long store short, this is for historical reasons. Way back in pre-1.0 times the intent was to follow our Unix code in searching the child'sPATH
. However, after several refactorings this became super buggy and only really worked ifCommand::env
was used. In other cases it (unintentionally) fell back to the standard CreateProcess rules.Awhile back it was decided to remove the current directory from the Windows
Command
search path. Which I did. At the time I was a bit worried it would affect people. But as it turned out that didn't appear to have that much of an impact. Or at least I've not heard of anyone having serious issues with it.I did however preserve some of the buggy
env
behaviour because, I was worried about making too many changes at once.. However, I do think it needs fixing somehowMotivating examples or use cases
Assuming that there is an app called
hello.exe
alongside the current application and also a differenthello.exe
inPATH
:Background
Windows
CreateProcess
search orderWhen using
CreateProcess
and not settinglpApplicationName
, it will attempt to discover the application in the following places (and in this order):PATH
This is the order (or similar) used by most Windows applications and runtimes.
Rust's Unix search order
PATH
Note: Rather than using
execvpe
, Rust sets the environment after forking and then usesexecvp
. See https://github.com/rust-lang/rust/blob/ed49386d3aa3a445a9889707fd405df01723eced/library/std/src/sys/pal/unix/process/process_unix.rs#L395Rust's Windows search order
PATH
but only if the child environment is not inherited.PATH
Obviously this leads to some inconsistencies depending on whether
Command::env
is used or not.It was originally intended we just do
1.
; so this search order was somewhat accidental.Solution sketch
There is a tension here between being consistent cross-platform and being consistent with non-Rust applications on Windows. We'd also prefer not break existing applications.
Trying to keep everyone happy is difficult, if not impossible but I think we can do better than we currently are. With that in mind, I would like the search order to be consistently:
PATH
but only if the child environment is not inherited.PATH
This is more or less the same as now except that the parent process' directory and system directories are consistently searched first.
I'd love to only check either the parent's or child's
PATH
, not both, but I worry that would be too breaking.Alternatives
PATH
at all.PATH
.PATH
(i.e. not the application or system directories).Links and related work
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
Second, if there's a concrete solution:
The text was updated successfully, but these errors were encountered: