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

process: add from_std to ChildStd* #4045

Merged
merged 2 commits into from
Aug 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 51 additions & 6 deletions tokio/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ pub struct Command {

pub(crate) struct SpawnedChild {
child: imp::Child,
stdin: Option<imp::ChildStdin>,
stdout: Option<imp::ChildStdout>,
stderr: Option<imp::ChildStderr>,
stdin: Option<imp::ChildStdio>,
stdout: Option<imp::ChildStdio>,
stderr: Option<imp::ChildStdio>,
}

impl Command {
Expand Down Expand Up @@ -1151,7 +1151,7 @@ impl Child {
/// handle of a child process asynchronously.
#[derive(Debug)]
pub struct ChildStdin {
inner: imp::ChildStdin,
inner: imp::ChildStdio,
}

/// The standard output stream for spawned children.
Expand All @@ -1160,7 +1160,7 @@ pub struct ChildStdin {
/// handle of a child process asynchronously.
#[derive(Debug)]
pub struct ChildStdout {
inner: imp::ChildStdout,
inner: imp::ChildStdio,
}

/// The standard error stream for spawned children.
Expand All @@ -1169,7 +1169,52 @@ pub struct ChildStdout {
/// handle of a child process asynchronously.
#[derive(Debug)]
pub struct ChildStderr {
inner: imp::ChildStderr,
inner: imp::ChildStdio,
}

impl ChildStdin {
/// Create an asynchronous `ChildStdin` from a synchronous one.
///
/// # Errors
///
/// This method may fail if an error is encountered when setting the pipe to
/// non-blocking mode, or when registering the pipe with the runtime's IO
/// driver.
pub fn from_std(inner: std::process::ChildStdin) -> io::Result<Self> {
Ok(Self {
inner: imp::stdio(inner)?,
})
}
}

impl ChildStdout {
/// Create an asynchronous `ChildStderr` from a synchronous one.
///
/// # Errors
///
/// This method may fail if an error is encountered when setting the pipe to
/// non-blocking mode, or when registering the pipe with the runtime's IO
/// driver.
pub fn from_std(inner: std::process::ChildStdout) -> io::Result<Self> {
Ok(Self {
inner: imp::stdio(inner)?,
})
}
}

impl ChildStderr {
/// Create an asynchronous `ChildStderr` from a synchronous one.
///
/// # Errors
///
/// This method may fail if an error is encountered when setting the pipe to
/// non-blocking mode, or when registering the pipe with the runtime's IO
/// driver.
pub fn from_std(inner: std::process::ChildStderr) -> io::Result<Self> {
Ok(Self {
inner: imp::stdio(inner)?,
})
}
}

impl AsyncWrite for ChildStdin {
Expand Down
19 changes: 6 additions & 13 deletions tokio/src/process/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ impl fmt::Debug for Child {

pub(crate) fn spawn_child(cmd: &mut std::process::Command) -> io::Result<SpawnedChild> {
let mut child = cmd.spawn()?;
let stdin = stdio(child.stdin.take())?;
let stdout = stdio(child.stdout.take())?;
let stderr = stdio(child.stderr.take())?;
let stdin = child.stdin.take().map(stdio).transpose()?;
let stdout = child.stdout.take().map(stdio).transpose()?;
let stderr = child.stderr.take().map(stdio).transpose()?;

let signal = signal(SignalKind::child())?;

Expand Down Expand Up @@ -213,9 +213,7 @@ impl Source for Pipe {
}
}

pub(crate) type ChildStdin = PollEvented<Pipe>;
pub(crate) type ChildStdout = PollEvented<Pipe>;
pub(crate) type ChildStderr = PollEvented<Pipe>;
pub(crate) type ChildStdio = PollEvented<Pipe>;

fn set_nonblocking<T: AsRawFd>(fd: &mut T, nonblocking: bool) -> io::Result<()> {
unsafe {
Expand All @@ -240,18 +238,13 @@ fn set_nonblocking<T: AsRawFd>(fd: &mut T, nonblocking: bool) -> io::Result<()>
Ok(())
}

fn stdio<T>(option: Option<T>) -> io::Result<Option<PollEvented<Pipe>>>
pub(super) fn stdio<T>(io: T) -> io::Result<PollEvented<Pipe>>
where
T: IntoRawFd,
{
let io = match option {
Some(io) => io,
None => return Ok(None),
};

// Set the fd to nonblocking before we pass it to the event loop
let mut pipe = Pipe::from(io);
set_nonblocking(&mut pipe, true)?;

Ok(Some(PollEvented::new(pipe)?))
PollEvented::new(pipe)
}
18 changes: 6 additions & 12 deletions tokio/src/process/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ unsafe impl Send for Waiting {}

pub(crate) fn spawn_child(cmd: &mut StdCommand) -> io::Result<SpawnedChild> {
let mut child = cmd.spawn()?;
let stdin = stdio(child.stdin.take());
let stdout = stdio(child.stdout.take());
let stderr = stdio(child.stderr.take());
let stdin = child.stdin.take().map(stdio).transpose()?;
let stdout = child.stdout.take().map(stdio).transpose()?;
let stderr = child.stderr.take().map(stdio).transpose()?;

Ok(SpawnedChild {
child: Child {
Expand Down Expand Up @@ -167,20 +167,14 @@ unsafe extern "system" fn callback(ptr: PVOID, _timer_fired: BOOLEAN) {
let _ = complete.take().unwrap().send(());
}

pub(crate) type ChildStdin = PollEvented<NamedPipe>;
pub(crate) type ChildStdout = PollEvented<NamedPipe>;
pub(crate) type ChildStderr = PollEvented<NamedPipe>;
pub(crate) type ChildStdio = PollEvented<NamedPipe>;

fn stdio<T>(option: Option<T>) -> Option<PollEvented<NamedPipe>>
pub(super) fn stdio<T>(io: T) -> io::Result<PollEvented<NamedPipe>>
where
T: IntoRawHandle,
{
let io = match option {
Some(io) => io,
None => return None,
};
let pipe = unsafe { NamedPipe::from_raw_handle(io.into_raw_handle()) };
PollEvented::new(pipe).ok()
PollEvented::new(pipe)
}

pub(crate) fn convert_to_stdio(io: PollEvented<NamedPipe>) -> io::Result<Stdio> {
Expand Down