-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Use argv[0] for cargo_exe so we don't rely on /proc on Linux #4634
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @matklad (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
src/cargo/util/config.rs
Outdated
@@ -154,7 +154,7 @@ impl Config { | |||
/// Get the path to the `cargo` executable | |||
pub fn cargo_exe(&self) -> CargoResult<&Path> { | |||
self.cargo_exe.get_or_try_init(|| | |||
env::current_exe().and_then(|path| path.canonicalize()) | |||
env::var(::CARGO_ENV).map(PathBuf::from).or_else(|_| env::current_exe().and_then(|path| path.canonicalize())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't canonicalise in both cases on purpose, i.e.:
env::var(::CARGO_ENV).map(PathBuf::from).or_else(|_| env::current_exe()).and_then(|path| path.canonicalize())
I figure if the user is supplying their own, we can trust them to select an appropriate incantation. (And if this is one we've propagated ourselves, we'll have canonicalised it here first.)
An alternative solution which comes to mind is a fallback to looking |
That was my first thought! It might work, but it might not, depending on the use case. The original issue at #3778 (comment) which introduced this env var said:
This provides a means to continue to provide the reassurance that it won't suddenly switch to the first |
"the tiny fraction of cases in which that was the case", wow. Can you tell I should be asleep already? |
Yeah, now that I think of it, your solution seems great to me! Let's ask @alexcrichton thoughts though? I think we might want to document this here https://github.com/rust-lang/cargo/blob/master/src/doc/environment-variables.md or here (I am totally confused: why do we have two sets of docs? 🤷♂️ ) And we might want to provide a custom warning message along the lines of
|
You're right about documentation and the better error message. I'll add those if Alex thinks this looks okay. 👍 |
Thanks for the PR! I'm a little wary of using a |
@alexcrichton Ah, yes; that's a way better solution! Will do. |
Looking good except for a broken test on Windows (because a UNC-style |
src/cargo/util/config.rs
Outdated
@@ -100,7 +101,7 @@ impl Config { | |||
} | |||
} | |||
|
|||
pub fn default() -> CargoResult<Config> { | |||
pub fn default(cargo_exe: PathBuf) -> CargoResult<Config> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we, instead of passing an argument to default
method, call std::env::args
here? default
method with an argument looks funny :)
Also, perhaps we should try to use current_exec
first, and only then fall-back to using argv[0]
? I don't have any solid arguments pro or contra, but using current_exec
seems appropriate in most cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah I agree with @matklad that using current_exe
first and then falling back to env::args
is probably the best strategy here
Thanks! One other comment I'd have is that when using |
I was thinking |
Here's the latest attempt:
The code is a bit janky; curious for your feedback. |
Looks reasonable to me! It's sort of unfortunate but AFAIK this is the only solution to " Mind adding some comments for why we have these fallbacks? |
Excellent call! Done. |
src/cargo/util/config.rs
Outdated
.and_then(|argv0| argv0.canonicalize().or_else(|_| probe_path(argv0))) | ||
} | ||
|
||
fn probe_path(argv0: PathBuf) -> CargoResult<PathBuf> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something similar happens in execute_external_subcommand
, but I don't think we can reasonable extract common functionality here.
Hm, what I still don't find perfect about current approach is that we still get a hard error if we fail to resolve current_exe, although we actually unlikely to use it at all (that is, we need to set CARGO variable when executing any target process, but few target processes actually use CARGO). Could we just avoid settings this environmental variable if we failed to get path to an executable (with a warning)? Also, does this have any security implications? Will it be possible to make, for example, a custom subcommand execute an arbitrary process instead of Cargo by, for example, placing a binary in a relative path so that canonicalize resolves to it? |
I'd be a little wary to proceed to execute a build script without a |
I'm +1 for erroring out; it means we can catch the weird case and maybe do something about it like we did in #4450. |
@matklad thoughts? |
I don't have a strong opinion here, so I am happy with either solution, although I am especially not sure about this line: https://github.com/rust-lang/cargo/pull/4634/files#diff-4559bc8f75ebf0a4d42be6e4e7fe9eaaR170. Looks like because of this we can put in I am thinking about "failing silently" because it seems that few builds actually use |
Summarising what to do in case
|
@kivikakk oh, wait, So yeah, I believe your last comment is absolutely correct and precise, thanks for clarifying it to me! |
@bors r+ Thanks!!! |
📌 Commit 1bb43b0 has been approved by |
Use argv[0] for cargo_exe so we don't rely on /proc on Linux This is a proposed solution to #4450. I'm not at all wedded to the idea or the code, though, so feel free to shoot it down with abandon if this isn't something that'd work out or that you like. In short, we use the existing `CARGO_ENV` (`"CARGO"`) if present, and only if not do we attempt to perform a lookup with `env::current_exe()` ourselves. This means users without access to `current_exe` (such as Linux without `procfs` mounted) can supply the `CARGO` env var themselves for external commands to use. My concern here is: what if maybe we intentionally switch cargo binaries and didn't intend for this to happen? Could this ever happen outside a test environment? This kind-of-sorta-happened by accident in the test suite, necessitating the explicit removal of `CARGO_ENV` from the subprocess environment, because the actual cargo executing the test suite propagated its own path into the test subprocess! /cc @alexcrichton as the originator of the idea of `CARGO_ENV`
To make it super clear, I intended to ban relative paths altogether, because I thought (wrongly), that argv[0] can't be relative. However, it can be relative, but it better be explicitly relative, so that's where the special case of a single components comes from 😆 |
☀️ Test successful - status-appveyor, status-travis |
This is a proposed solution to #4450. I'm not at all wedded to the idea or the code, though, so feel free to shoot it down with abandon if this isn't something that'd work out or that you like.
In short, we use the existing
CARGO_ENV
("CARGO"
) if present, and only if not do we attempt to perform a lookup withenv::current_exe()
ourselves. This means users without access tocurrent_exe
(such as Linux withoutprocfs
mounted) can supply theCARGO
env var themselves for external commands to use.My concern here is: what if maybe we intentionally switch cargo binaries and didn't intend for this to happen? Could this ever happen outside a test environment? This kind-of-sorta-happened by accident in the test suite, necessitating the explicit removal of
CARGO_ENV
from the subprocess environment, because the actual cargo executing the test suite propagated its own path into the test subprocess!/cc @alexcrichton as the originator of the idea of
CARGO_ENV