process: Add Windows support for stdio streams

This commit is contained in:
Alex Crichton
2019-06-24 16:56:47 -07:00
committed by Ivan Petkov
parent 97ebb2275c
commit 7f3f868b66
5 changed files with 211 additions and 130 deletions
+48 -5
View File
@@ -1,12 +1,15 @@
extern crate winapi;
extern crate kernel32;
extern crate mio_named_pipes;
use std::io;
use std::os::windows::prelude::*;
use std::os::windows::process::ExitStatusExt;
use std::process::{self, ExitStatus};
use tokio_core::reactor::{PollEvented, Handle};
use futures::{self, Future, Poll, Async, Oneshot, Complete, oneshot, Fuse};
use self::mio_named_pipes::NamedPipe;
use Command;
@@ -24,12 +27,35 @@ struct Waiting {
unsafe impl Sync for Waiting {}
unsafe impl Send for Waiting {}
pub fn spawn(mut cmd: Command) -> Box<Future<Item=Child, Error=io::Error>> {
Box::new(futures::done(cmd.inner.spawn().map(|c| {
Child {
child: c,
waiting: None,
pub fn spawn(mut cmd: Command) -> Box<Future<Item=::Child, Error=io::Error>> {
struct KillOnDrop(Option<process::Child>);
impl Drop for KillOnDrop {
fn drop(&mut self) {
if let Some(mut c) = self.0.take() {
drop(c.kill());
}
}
}
Box::new(futures::done(cmd.inner.spawn().and_then(|mut c| {
let stdin = c.stdin.take();
let stdout = c.stdout.take();
let stderr = c.stderr.take();
let mut c = KillOnDrop(Some(c));
let stdin = try!(stdio(stdin, &cmd.handle));
let stdout = try!(stdio(stdout, &cmd.handle));
let stderr = try!(stdio(stderr, &cmd.handle));
Ok(::Child {
inner: Child {
child: c.0.take().unwrap(),
waiting: None,
},
stdin: stdin.map(|io| ::ChildStdin { inner: io }),
stdout: stdout.map(|io| ::ChildStdout { inner: io }),
stderr: stderr.map(|io| ::ChildStderr { inner: io }),
})
})))
}
@@ -121,3 +147,20 @@ pub fn try_wait(child: &process::Child) -> io::Result<Option<ExitStatus>> {
}
}
}
pub type ChildStdin = PollEvented<NamedPipe>;
pub type ChildStdout = PollEvented<NamedPipe>;
pub type ChildStderr = PollEvented<NamedPipe>;
fn stdio<T>(option: Option<T>, handle: &Handle)
-> io::Result<Option<PollEvented<NamedPipe>>>
where T: IntoRawHandle,
{
let io = match option {
Some(io) => io,
None => return Ok(None),
};
let pipe = unsafe { NamedPipe::from_raw_handle(io.into_raw_handle()) };
let io = try!(PollEvented::new(pipe, handle));
Ok(Some(io))
}