Skip to content

std::process::Command's current_dir behaves differently on Unix and Windows, with respect to relative exe paths #37868

Open
@oconnor663

Description

@oconnor663

On Unix, relative paths to the exe are interpreted after cd'ing to the current_dir, but on Windows they're interpreted before. Here's an example test (1 test file, and 1 little binary that the test needs to build) that demonstrates this if you run cargo test on the two different platforms:

src/lib.rs

#[test]
fn execute_binary_from_another_dir() {
    // Run `cargo build` to make sure the associated `foo` binary gets built.
    std::process::Command::new("cargo").arg("build").status().unwrap();

    // Shell out to `foo`, just to confirm that this works fine.
    std::process::Command::new("target/debug/foo")
        .status()
        .unwrap();

    // Now try to shell out to `foo` again while also setting the current_dir.
    // This fails on Unix, because the path to the binary is resolved *after*
    // changing directories, but it works on Windows.
    std::process::Command::new("target/debug/foo")
        .current_dir("..")
        .status()
        .unwrap();
}

src/bin/foo.rs

fn main() {
    println!("foo!");
}

I ran into a similar difference when I tried this with Python's subprocess.run(..., cwd=...). It looks like it's an artifact of Windows supporting an lpCurrentDirectory arg natively, while Unix has to fork and then chdir in the child before it calls exec. I prefer the semantics that we're getting on Windows right now*, but this issue is mainly that they're not the same.

* My main reason for preferring the current-Windows-style "current_dir does not affect the exe location" semantics: Emulating the current-Unix-style only requires a Path::join, which always works. But going the other way requires a Path::canonicalize, which can fail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-processArea: `std::process` and `std::env`C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions