Skip to content

Commit 6259670

Browse files
Revert "Auto merge of #96441 - ChrisDenton:sync-pipes, r=m-ou-se"
This reverts commit ddb7fbe, reversing changes made to baaa3b6.
1 parent 4c5f6e6 commit 6259670

File tree

5 files changed

+31
-132
lines changed

5 files changed

+31
-132
lines changed

library/std/src/os/windows/io/handle.rs

-13
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,6 @@ impl OwnedHandle {
204204
})?;
205205
unsafe { Ok(Self::from_raw_handle(ret)) }
206206
}
207-
208-
/// Allow child processes to inherit the handle.
209-
#[cfg(not(target_vendor = "uwp"))]
210-
pub(crate) fn set_inheritable(&self) -> io::Result<()> {
211-
cvt(unsafe {
212-
c::SetHandleInformation(
213-
self.as_raw_handle(),
214-
c::HANDLE_FLAG_INHERIT,
215-
c::HANDLE_FLAG_INHERIT,
216-
)
217-
})?;
218-
Ok(())
219-
}
220207
}
221208

222209
impl TryFrom<HandleOrInvalid> for OwnedHandle {

library/std/src/sys/windows/c.rs

-6
Original file line numberDiff line numberDiff line change
@@ -1022,12 +1022,6 @@ extern "system" {
10221022
bWaitAll: BOOL,
10231023
dwMilliseconds: DWORD,
10241024
) -> DWORD;
1025-
pub fn CreatePipe(
1026-
hReadPipe: *mut HANDLE,
1027-
hWritePipe: *mut HANDLE,
1028-
lpPipeAttributes: *const SECURITY_ATTRIBUTES,
1029-
nSize: DWORD,
1030-
) -> BOOL;
10311025
pub fn CreateNamedPipeW(
10321026
lpName: LPCWSTR,
10331027
dwOpenMode: DWORD,

library/std/src/sys/windows/handle.rs

-5
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,6 @@ impl Handle {
221221
Ok(Self(self.0.duplicate(access, inherit, options)?))
222222
}
223223

224-
#[cfg(not(target_vendor = "uwp"))]
225-
pub(crate) fn set_inheritable(&self) -> io::Result<()> {
226-
self.0.set_inheritable()
227-
}
228-
229224
/// Performs a synchronous read.
230225
///
231226
/// If the handle is opened for asynchronous I/O then this abort the process.

library/std/src/sys/windows/pipe.rs

+25-76
Original file line numberDiff line numberDiff line change
@@ -18,67 +18,20 @@ use crate::sys_common::IntoInner;
1818
// Anonymous pipes
1919
////////////////////////////////////////////////////////////////////////////////
2020

21-
// A 64kb pipe capacity is the same as a typical Linux default.
22-
const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024;
23-
24-
pub enum AnonPipe {
25-
Sync(Handle),
26-
Async(Handle),
21+
pub struct AnonPipe {
22+
inner: Handle,
2723
}
2824

2925
impl IntoInner<Handle> for AnonPipe {
3026
fn into_inner(self) -> Handle {
31-
match self {
32-
Self::Sync(handle) => handle,
33-
Self::Async(handle) => handle,
34-
}
27+
self.inner
3528
}
3629
}
3730

3831
pub struct Pipes {
3932
pub ours: AnonPipe,
4033
pub theirs: AnonPipe,
4134
}
42-
impl Pipes {
43-
/// Create a new pair of pipes where both pipes are synchronous.
44-
///
45-
/// These must not be used asynchronously.
46-
pub fn new_synchronous(
47-
ours_readable: bool,
48-
their_handle_inheritable: bool,
49-
) -> io::Result<Self> {
50-
unsafe {
51-
// If `CreatePipe` succeeds, these will be our pipes.
52-
let mut read = ptr::null_mut();
53-
let mut write = ptr::null_mut();
54-
55-
if c::CreatePipe(&mut read, &mut write, ptr::null(), PIPE_BUFFER_CAPACITY) == 0 {
56-
Err(io::Error::last_os_error())
57-
} else {
58-
let (ours, theirs) = if ours_readable { (read, write) } else { (write, read) };
59-
let ours = Handle::from_raw_handle(ours);
60-
#[cfg(not(target_vendor = "uwp"))]
61-
let theirs = Handle::from_raw_handle(theirs);
62-
#[cfg(target_vendor = "uwp")]
63-
let mut theirs = Handle::from_raw_handle(theirs);
64-
65-
if their_handle_inheritable {
66-
#[cfg(not(target_vendor = "uwp"))]
67-
{
68-
theirs.set_inheritable()?;
69-
}
70-
71-
#[cfg(target_vendor = "uwp")]
72-
{
73-
theirs = theirs.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?;
74-
}
75-
}
76-
77-
Ok(Pipes { ours: AnonPipe::Sync(ours), theirs: AnonPipe::Sync(theirs) })
78-
}
79-
}
80-
}
81-
}
8235

8336
/// Although this looks similar to `anon_pipe` in the Unix module it's actually
8437
/// subtly different. Here we'll return two pipes in the `Pipes` return value,
@@ -100,6 +53,9 @@ impl Pipes {
10053
/// with `OVERLAPPED` instances, but also works out ok if it's only ever used
10154
/// once at a time (which we do indeed guarantee).
10255
pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result<Pipes> {
56+
// A 64kb pipe capacity is the same as a typical Linux default.
57+
const PIPE_BUFFER_CAPACITY: u32 = 64 * 1024;
58+
10359
// Note that we specifically do *not* use `CreatePipe` here because
10460
// unfortunately the anonymous pipes returned do not support overlapped
10561
// operations. Instead, we create a "hopefully unique" name and create a
@@ -200,9 +156,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
200156
};
201157
opts.security_attributes(&mut sa);
202158
let theirs = File::open(Path::new(&name), &opts)?;
203-
let theirs = AnonPipe::Sync(theirs.into_inner());
159+
let theirs = AnonPipe { inner: theirs.into_inner() };
204160

205-
Ok(Pipes { ours: AnonPipe::Async(ours), theirs })
161+
Ok(Pipes {
162+
ours: AnonPipe { inner: ours },
163+
theirs: AnonPipe { inner: theirs.into_inner() },
164+
})
206165
}
207166
}
208167

@@ -212,12 +171,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
212171
/// This is achieved by creating a new set of pipes and spawning a thread that
213172
/// relays messages between the source and the synchronous pipe.
214173
pub fn spawn_pipe_relay(
215-
source: &Handle,
174+
source: &AnonPipe,
216175
ours_readable: bool,
217176
their_handle_inheritable: bool,
218177
) -> io::Result<AnonPipe> {
219178
// We need this handle to live for the lifetime of the thread spawned below.
220-
let source = AnonPipe::Async(source.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?);
179+
let source = source.duplicate()?;
221180

222181
// create a new pair of anon pipes.
223182
let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?;
@@ -268,24 +227,19 @@ type AlertableIoFn = unsafe extern "system" fn(
268227

269228
impl AnonPipe {
270229
pub fn handle(&self) -> &Handle {
271-
match self {
272-
Self::Async(ref handle) => handle,
273-
Self::Sync(ref handle) => handle,
274-
}
230+
&self.inner
275231
}
276232
pub fn into_handle(self) -> Handle {
277-
self.into_inner()
233+
self.inner
234+
}
235+
fn duplicate(&self) -> io::Result<Self> {
236+
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner })
278237
}
279238

280239
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
281240
let result = unsafe {
282241
let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
283-
match self {
284-
Self::Sync(ref handle) => handle.read(buf),
285-
Self::Async(_) => {
286-
self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len)
287-
}
288-
}
242+
self.alertable_io_internal(c::ReadFileEx, buf.as_mut_ptr() as _, len)
289243
};
290244

291245
match result {
@@ -299,33 +253,28 @@ impl AnonPipe {
299253
}
300254

301255
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
302-
io::default_read_vectored(|buf| self.read(buf), bufs)
256+
self.inner.read_vectored(bufs)
303257
}
304258

305259
#[inline]
306260
pub fn is_read_vectored(&self) -> bool {
307-
false
261+
self.inner.is_read_vectored()
308262
}
309263

310264
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
311265
unsafe {
312266
let len = crate::cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
313-
match self {
314-
Self::Sync(ref handle) => handle.write(buf),
315-
Self::Async(_) => {
316-
self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len)
317-
}
318-
}
267+
self.alertable_io_internal(c::WriteFileEx, buf.as_ptr() as _, len)
319268
}
320269
}
321270

322271
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
323-
io::default_write_vectored(|buf| self.write(buf), bufs)
272+
self.inner.write_vectored(bufs)
324273
}
325274

326275
#[inline]
327276
pub fn is_write_vectored(&self) -> bool {
328-
false
277+
self.inner.is_write_vectored()
329278
}
330279

331280
/// Synchronizes asynchronous reads or writes using our anonymous pipe.
@@ -397,7 +346,7 @@ impl AnonPipe {
397346

398347
// Asynchronous read of the pipe.
399348
// If successful, `callback` will be called once it completes.
400-
let result = io(self.handle().as_handle(), buf, len, &mut overlapped, callback);
349+
let result = io(self.inner.as_handle(), buf, len, &mut overlapped, callback);
401350
if result == c::FALSE {
402351
// We can return here because the call failed.
403352
// After this we must not return until the I/O completes.

library/std/src/sys/windows/process.rs

+6-32
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::sys::cvt;
2323
use crate::sys::fs::{File, OpenOptions};
2424
use crate::sys::handle::Handle;
2525
use crate::sys::path;
26-
use crate::sys::pipe::{self, AnonPipe, Pipes};
26+
use crate::sys::pipe::{self, AnonPipe};
2727
use crate::sys::stdio;
2828
use crate::sys_common::mutex::StaticMutex;
2929
use crate::sys_common::process::{CommandEnv, CommandEnvs};
@@ -172,7 +172,7 @@ pub enum Stdio {
172172
Inherit,
173173
Null,
174174
MakePipe,
175-
AsyncPipe(Handle),
175+
Pipe(AnonPipe),
176176
Handle(Handle),
177177
}
178178

@@ -527,33 +527,13 @@ impl Stdio {
527527
},
528528

529529
Stdio::MakePipe => {
530-
// Handles that are passed to a child process must be synchronous
531-
// because they will be read synchronously (see #95759).
532-
// Therefore we prefer to make both ends of a pipe synchronous
533-
// just in case our end of the pipe is passed to another process.
534-
//
535-
// However, we may need to read from both the child's stdout and
536-
// stderr simultaneously when waiting for output. This requires
537-
// async reads so as to avoid blocking either pipe.
538-
//
539-
// The solution used here is to make handles synchronous
540-
// except for our side of the stdout and sterr pipes.
541-
// If our side of those pipes do end up being given to another
542-
// process then we use a "pipe relay" to synchronize access
543-
// (see `Stdio::AsyncPipe` below).
544-
let pipes = if stdio_id == c::STD_INPUT_HANDLE {
545-
// For stdin both sides of the pipe are synchronous.
546-
Pipes::new_synchronous(false, true)?
547-
} else {
548-
// For stdout/stderr our side of the pipe is async and their side is synchronous.
549-
pipe::anon_pipe(true, true)?
550-
};
530+
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
531+
let pipes = pipe::anon_pipe(ours_readable, true)?;
551532
*pipe = Some(pipes.ours);
552533
Ok(pipes.theirs.into_handle())
553534
}
554535

555-
Stdio::AsyncPipe(ref source) => {
556-
// We need to synchronize asynchronous pipes by using a pipe relay.
536+
Stdio::Pipe(ref source) => {
557537
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
558538
pipe::spawn_pipe_relay(source, ours_readable, true).map(AnonPipe::into_handle)
559539
}
@@ -582,13 +562,7 @@ impl Stdio {
582562

583563
impl From<AnonPipe> for Stdio {
584564
fn from(pipe: AnonPipe) -> Stdio {
585-
// Note that it's very important we don't give async handles to child processes.
586-
// Therefore if the pipe is asynchronous we must have a way to turn it synchronous.
587-
// See #95759.
588-
match pipe {
589-
AnonPipe::Sync(handle) => Stdio::Handle(handle),
590-
AnonPipe::Async(handle) => Stdio::AsyncPipe(handle),
591-
}
565+
Stdio::Pipe(pipe)
592566
}
593567
}
594568

0 commit comments

Comments
 (0)