mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-13 00:56:14 +00:00
Windows: Use a pipe relay for chaining pipes
This commit is contained in:
parent
e745b4ddbd
commit
90130549f4
@ -162,6 +162,46 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes an asynchronous source pipe and returns a synchronous pipe suitable
|
||||
/// for sending to a child process.
|
||||
///
|
||||
/// This is achieved by creating a new set of pipes and spawning a thread that
|
||||
/// relays messages between the source and the synchronous pipe.
|
||||
pub fn spawn_pipe_relay(
|
||||
source: &AnonPipe,
|
||||
ours_readable: bool,
|
||||
their_handle_inheritable: bool,
|
||||
) -> io::Result<AnonPipe> {
|
||||
// We need this handle to live for the lifetime of the thread spawned below.
|
||||
let source = source.duplicate()?;
|
||||
|
||||
// create a new pair of anon pipes.
|
||||
let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?;
|
||||
|
||||
// Spawn a thread that passes messages from one pipe to the other.
|
||||
// Any errors will simply cause the thread to exit.
|
||||
let (reader, writer) = if ours_readable { (ours, source) } else { (source, ours) };
|
||||
crate::thread::spawn(move || {
|
||||
let mut buf = [0_u8; 4096];
|
||||
'reader: while let Ok(len) = reader.read(&mut buf) {
|
||||
if len == 0 {
|
||||
break;
|
||||
}
|
||||
let mut start = 0;
|
||||
while let Ok(written) = writer.write(&buf[start..len]) {
|
||||
start += written;
|
||||
if start == len {
|
||||
continue 'reader;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Return the pipe that should be sent to the child process.
|
||||
Ok(theirs)
|
||||
}
|
||||
|
||||
fn random_number() -> usize {
|
||||
static N: AtomicUsize = AtomicUsize::new(0);
|
||||
loop {
|
||||
@ -189,6 +229,9 @@ impl AnonPipe {
|
||||
pub fn into_handle(self) -> Handle {
|
||||
self.inner
|
||||
}
|
||||
fn duplicate(&self) -> io::Result<Self> {
|
||||
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner })
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let result = unsafe {
|
||||
|
@ -172,6 +172,7 @@ pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
MakePipe,
|
||||
Pipe(AnonPipe),
|
||||
Handle(Handle),
|
||||
}
|
||||
|
||||
@ -528,6 +529,11 @@ impl Stdio {
|
||||
Ok(pipes.theirs.into_handle())
|
||||
}
|
||||
|
||||
Stdio::Pipe(ref source) => {
|
||||
let ours_readable = stdio_id != c::STD_INPUT_HANDLE;
|
||||
pipe::spawn_pipe_relay(source, ours_readable, true).map(AnonPipe::into_handle)
|
||||
}
|
||||
|
||||
Stdio::Handle(ref handle) => handle.duplicate(0, true, c::DUPLICATE_SAME_ACCESS),
|
||||
|
||||
// Open up a reference to NUL with appropriate read/write
|
||||
@ -552,7 +558,7 @@ impl Stdio {
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
Stdio::Handle(pipe.into_handle())
|
||||
Stdio::Pipe(pipe)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user