mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #153469 - Albab-Hasan:doc/command-path-search-behavior, r=ChrisDenton
docs: clarify path search behavior in std::process::Command::new the existing docs mentioned that `PATH` is searched in an "os defined way" and that it could be controlled by setting PATH on the command but never explained which `PATH` is actually used. on unix the key thing to understand is that when you modify the childs environment (via `env()`, `env_remove()`, or `env_clear()`), the `PATH` search uses whatever `PATH` ends up in the child's environment not the parents. so if you call `env_clear()` and forget to set `PATH`, you don't get the parents `PATH` as a fallback; you get the OS default (typically `/bin:/usr/bin`) which often won't find what you need. the three cases are now documented: - unmodified env: child inherits parents `PATH`, that gets searched - `PATH` explicitly set `via env()`: the new value is searched - `PATH` removed (`env_clear` or `env_remove`): falls back to OS default, not the parents `PATH` on windows rust resolves the executable before spawning rather than letting `CreateProcessW` do it. the search order is: childs `PATH` (if explicitly set) first then system-defined directories then the parents `PATH`. the existing note about issue rust-lang/rust#37519 is preserved. limitations in this doc: - the unix fallback path behavior ("typically `/bin:/usr/bin`") is verified for linux/glibc. behavior on macOS, BSD, and musl is similar in practice but not fully confirmed here. - the windows search order is summarized as "system-defined directories" which actually includes the application directory (the directory of the calling process's executable) as a distinct step before the system dirs that detail is omitted for brevity. - `posix_spawnp` `PATH` source (calling process environ vs envp argument) is ambiguous in the `POSIX` spec; the behavior here is inferred from the guard in `unix.rs` that bypasses `posix_spawn` when `PATH` has been modified. closes rust-lang/rust#137286 (hopefully)
This commit is contained in:
+41
-12
@@ -617,21 +617,50 @@ impl Command {
|
||||
/// Builder methods are provided to change these defaults and
|
||||
/// otherwise configure the process.
|
||||
///
|
||||
/// If `program` is not an absolute path, the `PATH` will be searched in
|
||||
/// an OS-defined way.
|
||||
///
|
||||
/// The search path to be used may be controlled by setting the
|
||||
/// `PATH` environment variable on the Command,
|
||||
/// but this has some implementation limitations on Windows
|
||||
/// (see issue #37519).
|
||||
/// If `program` is not an absolute path, the `PATH` environment variable
|
||||
/// will be searched in an OS-defined way.
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
/// Note on Windows: For executable files with the .exe extension,
|
||||
/// it can be omitted when specifying the program for this Command.
|
||||
/// However, if the file has a different extension,
|
||||
/// a filename including the extension needs to be provided,
|
||||
/// otherwise the file won't be found.
|
||||
/// The details below describe the current behavior, but these details
|
||||
/// may change in future versions of Rust.
|
||||
///
|
||||
/// On Unix, the `PATH` searched comes from the child's environment:
|
||||
///
|
||||
/// - If the environment is unmodified, the child inherits the parent's
|
||||
/// `PATH` and that is what is searched.
|
||||
/// - If `PATH` is explicitly set via [`env`], that new value is searched.
|
||||
/// - If [`env_clear`] or [`env_remove`] removes `PATH` without a
|
||||
/// replacement, `execvp` falls back to an OS-defined default (typically
|
||||
/// `/bin:/usr/bin`), **not** the parent's `PATH`. This may fail to find
|
||||
/// programs that rely on the parent's `PATH`.
|
||||
///
|
||||
/// To avoid surprises, use an absolute path or explicitly set `PATH` on
|
||||
/// the `Command` when modifying the child's environment.
|
||||
///
|
||||
/// On Windows, Rust resolves the executable path before spawning, rather
|
||||
/// than passing the name to `CreateProcessW` for resolution. When
|
||||
/// `program` is not an absolute path, the following locations are searched
|
||||
/// in order:
|
||||
///
|
||||
/// 1. The child's `PATH`, if explicitly set via [`env`].
|
||||
/// 2. The directory of the current executable.
|
||||
/// 3. The system directory (`GetSystemDirectoryW`).
|
||||
/// 4. The Windows directory (`GetWindowsDirectoryW`).
|
||||
/// 5. The parent process's `PATH`.
|
||||
///
|
||||
/// Note: when `PATH` is cleared via [`env_clear`] or [`env_remove`] on
|
||||
/// Windows, step 1 is skipped but the parent process's `PATH` is still
|
||||
/// searched at step 5, unlike on Unix.
|
||||
///
|
||||
/// For executable files, the `.exe` extension may be omitted. Files with
|
||||
/// other extensions must include the extension, otherwise they will not be
|
||||
/// found. Note that this behavior has some known limitations
|
||||
/// (see issue #37519).
|
||||
///
|
||||
/// [`env`]: Self::env
|
||||
/// [`env_remove`]: Self::env_remove
|
||||
/// [`env_clear`]: Self::env_clear
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user