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

Windows: std::process::Command may pass asynchronous pipes to child process #95759

Closed
ChrisDenton opened this issue Apr 7, 2022 · 5 comments · Fixed by #95841
Closed

Windows: std::process::Command may pass asynchronous pipes to child process #95759

ChrisDenton opened this issue Apr 7, 2022 · 5 comments · Fixed by #95841
Labels
C-bug Category: This is a bug. O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@ChrisDenton
Copy link
Member

ChrisDenton commented Apr 7, 2022

Rust assumes stdio handles are opened for synchronous access (as will most other Windows processes). However, when passing ChildStdOut, ChildStdIn or ChildStdErr to a new Command the pipes passed in are asynchronous. For a full test case see src/test/ui-fulldeps/stdio-from.rs but here's a shorter example:

fn try_it(a: &mut Child, b: &mut Child) -> io::Result<()> {
    let mut child = Command::new("application")
        .stdin(a.stdout.take().unwrap())
        .stdout(b.stdin.take().unwrap())
        .spawn()?;

    assert!(child.wait()?.success());
    Ok(())
}

This is related to an older issue: #38811 (comment)

This can cause soundness issues described in #81357.

@ChrisDenton ChrisDenton added O-windows Operating system: Windows C-bug Category: This is a bug. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Apr 7, 2022
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Apr 8, 2022
Windows: Increase a pipe's buffer capacity to 64kb

This brings it inline with typical Linux defaults: https://www.man7.org/linux/man-pages/man7/pipe.7.html

> Since Linux 2.6.11, the pipe capacity is 16 pages (i.e., 65,536 bytes in a system with a page size of 4096 bytes).

This may also help with rust-lang#45572 and rust-lang#95759 but does not fix either issue. It simply makes them much less likely to be encountered.
@RalfJung RalfJung mentioned this issue Apr 9, 2022
@RalfJung
Copy link
Member

This has now made #95848 fail 2 times in a row... is there some form of emergency patch that can be applied to resolve this issue?
Cc @rust-lang/infra since this will prevent unrelated PRs from landing.

@klensy
Copy link
Contributor

klensy commented Apr 10, 2022

There is #95841 fix, but it need to be reviewed :-)

@ChrisDenton
Copy link
Member Author

Yeah, I had hoped increasing the pipe buffer size would work well enough to make failures less common until a proper fix was implemented. But unfortunately it's still quite prone to failures.

I'm trying a different reviewer for #95841 in case they're more available right now.

@RalfJung
Copy link
Member

@ChrisDenton FWIW, there is still one thing I am confused by: what if someone spawns a program written in Rust using some means other than our own std::process (maybe not even from Rust but from another language). Couldn't they also end up passing async pipes to the Rust process? Would that be a problem? In other words, is "passed-in pipes must be synchronous" now part of the public API of every Rust binary? (That would seem quite bad, if on Windows some programs require to be spawned with sync pipes and some with async pipes. So I might be misunderstanding what happens here.)

@ChrisDenton
Copy link
Member Author

Sure they can spawn their process using asynchronous handles for stdio. They can even do that using std::process if they bring their own handles. But doing this properly would require the cooperation of the child process (e.g. they'd somehow have to just know the pipes are async).

I think it's more correct to say "passed-in pipes must be assumed to be synchronous" is part of the Windows API. And it's what we were always assuming (albeit unintentionally violating in certain circumstances).

@bors bors closed this as completed in 69a5ae3 Apr 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. O-windows Operating system: Windows T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants