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

std: Don't pass overlapped handles to processes #38835

Merged
merged 1 commit into from
Jan 7, 2017

Conversation

alexcrichton
Copy link
Member

This commit fixes a mistake introduced in #31618 where overlapped handles were
leaked to child processes on Windows. On Windows once a handle is in overlapped
mode it should always have I/O executed with an instance of OVERLAPPED. Most
child processes, however, are not prepared to have their stdio handles in
overlapped mode as they don't use OVERLAPPED on reads/writes to the handle.

Now we haven't had any odd behavior in Rust up to this point, and the original
bug was introduced almost a year ago. I believe this is because it turns out
that if you don't pass an OVERLAPPED then the system will supply one for
you
. In this case everything will go awry if you concurrently operate on
the handle. In Rust, however, the stdio handles are always locked, and there's
no way to not use them unlocked in libstd. Due to that change we've always had
synchronized access to these handles, which means that Rust programs typically
"just work".

Conversely, though, this commit fixes the test case included, which exhibits
behavior that other programs Rust spawns may attempt to execute. Namely, the
stdio handles may be concurrently used and having them in overlapped mode wreaks
havoc.

Closes #38811

This commit fixes a mistake introduced in rust-lang#31618 where overlapped handles were
leaked to child processes on Windows. On Windows once a handle is in overlapped
mode it should always have I/O executed with an instance of `OVERLAPPED`. Most
child processes, however, are not prepared to have their stdio handles in
overlapped mode as they don't use `OVERLAPPED` on reads/writes to the handle.

Now we haven't had any odd behavior in Rust up to this point, and the original
bug was introduced almost a year ago. I believe this is because it turns out
that if you *don't* pass an `OVERLAPPED` then the system will [supply one for
you][link]. In this case everything will go awry if you concurrently operate on
the handle. In Rust, however, the stdio handles are always locked, and there's
no way to not use them unlocked in libstd. Due to that change we've always had
synchronized access to these handles, which means that Rust programs typically
"just work".

Conversely, though, this commit fixes the test case included, which exhibits
behavior that other programs Rust spawns may attempt to execute. Namely, the
stdio handles may be concurrently used and having them in overlapped mode wreaks
havoc.

[link]: https://blogs.msdn.microsoft.com/oldnewthing/20121012-00/?p=6343

Closes rust-lang#38811
@rust-highfive
Copy link
Collaborator

r? @brson

(rust_highfive has picked a reviewer for you, use r? to override)

@alexcrichton
Copy link
Member Author

I'm also going to beta-nominate this issue due to it fixing a stable-to-stable regression, but if this rides the trains that also seems reasonable. For me if this passes the test suite I'd imagine it's ready to backport.

@alexcrichton alexcrichton added beta-nominated Nominated for backporting to the compiler in the beta channel. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jan 4, 2017
@brson brson added the beta-accepted Accepted for backporting to the compiler in the beta channel. label Jan 5, 2017
@brson
Copy link
Contributor

brson commented Jan 5, 2017

@bors r+

@bors
Copy link
Contributor

bors commented Jan 5, 2017

📌 Commit 5148918 has been approved by brson

@@ -54,11 +79,16 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
.encode_wide()
.chain(Some(0))
.collect::<Vec<_>>();
let mut flags = c::FILE_FLAG_FIRST_PIPE_INSTANCE |
c::FILE_FLAG_OVERLAPPED;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is weird here. I immediately assumed this was inside some conditional.

Copy link
Member

@nagisa nagisa Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d honestly prefer if it was written as such:

let access_flag = if ours_readable { PIPE_ACCESS_INBOUND } else { PIPE_ACCESS_OUTBOUND };
let handle = c::CreateNamedPipeW(wide_name.as_ptr(),
                                 PIPE_1 | 
                                 PIPE_2 | 
                                 access_flags, ...

@alexcrichton
Copy link
Member Author

@bors: p=1

This is a backport

@bors
Copy link
Contributor

bors commented Jan 6, 2017

⌛ Testing commit 5148918 with merge 309dcc9...

@bors
Copy link
Contributor

bors commented Jan 6, 2017

💔 Test failed - status-travis

@arielb1
Copy link
Contributor

arielb1 commented Jan 6, 2017

The command "if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then

    echo skipping, not a full build;

elif [ "$TRAVIS_OS_NAME" = "osx" ]; then

    git submodule update --init &&

    src/ci/run.sh;

else

    git submodule update --init &&

    src/ci/docker/run.sh $IMAGE;

fi

" exited with 129.

@bors retry

@bors
Copy link
Contributor

bors commented Jan 6, 2017

⌛ Testing commit 5148918 with merge 9429fdc...

@bors
Copy link
Contributor

bors commented Jan 6, 2017

💔 Test failed - status-travis

@nikomatsakis nikomatsakis mentioned this pull request Jan 6, 2017
17 tasks
@alexcrichton
Copy link
Member Author

alexcrichton commented Jan 6, 2017 via email

@nikomatsakis nikomatsakis mentioned this pull request Jan 6, 2017
6 tasks
@bors
Copy link
Contributor

bors commented Jan 6, 2017

⌛ Testing commit 5148918 with merge 7e38a89...

bors added a commit that referenced this pull request Jan 6, 2017
std: Don't pass overlapped handles to processes

This commit fixes a mistake introduced in #31618 where overlapped handles were
leaked to child processes on Windows. On Windows once a handle is in overlapped
mode it should always have I/O executed with an instance of `OVERLAPPED`. Most
child processes, however, are not prepared to have their stdio handles in
overlapped mode as they don't use `OVERLAPPED` on reads/writes to the handle.

Now we haven't had any odd behavior in Rust up to this point, and the original
bug was introduced almost a year ago. I believe this is because it turns out
that if you *don't* pass an `OVERLAPPED` then the system will [supply one for
you][link]. In this case everything will go awry if you concurrently operate on
the handle. In Rust, however, the stdio handles are always locked, and there's
no way to not use them unlocked in libstd. Due to that change we've always had
synchronized access to these handles, which means that Rust programs typically
"just work".

Conversely, though, this commit fixes the test case included, which exhibits
behavior that other programs Rust spawns may attempt to execute. Namely, the
stdio handles may be concurrently used and having them in overlapped mode wreaks
havoc.

[link]: https://blogs.msdn.microsoft.com/oldnewthing/20121012-00/?p=6343

Closes #38811
@bors
Copy link
Contributor

bors commented Jan 7, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: brson
Pushing 7e38a89 to master...

@bors bors merged commit 5148918 into rust-lang:master Jan 7, 2017
@alexcrichton alexcrichton deleted the less-overlapped branch January 7, 2017 05:44
@alexcrichton alexcrichton removed the beta-nominated Nominated for backporting to the compiler in the beta channel. label Jan 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
beta-accepted Accepted for backporting to the compiler in the beta channel. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

std::process::Command: piped stderr hangs in Windows
6 participants