diff --git a/src/bin/cat.rs b/src/bin/cat.rs index b982fceaa..7acfeb695 100644 --- a/src/bin/cat.rs +++ b/src/bin/cat.rs @@ -10,10 +10,10 @@ fn main() { loop { line.clear(); stdin.read_line(&mut line).unwrap(); - if line.len() == 0 { + if line.is_empty() { break; } - stdout.write(line.as_bytes()).unwrap(); + stdout.write_all(line.as_bytes()).unwrap(); } stdout.flush().unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index eced66ad6..26e60ec16 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -319,15 +319,21 @@ pub trait CommandExt { fn output_async_with_handle(&mut self, handle: &Handle) -> OutputAsync; } +struct SpawnedChild { + child: imp::Child, + stdin: Option, + stdout: Option, + stderr: Option, +} impl CommandExt for Command { fn spawn_async_with_handle(&mut self, handle: &Handle) -> io::Result { - imp::Child::new(self.spawn()?, handle) - .map(|(child, stdin, stdout, stderr)| Child { - child, - stdin: stdin.map(|inner| ChildStdin { inner }), - stdout: stdout.map(|inner| ChildStdout { inner }), - stderr: stderr.map(|inner| ChildStderr { inner }), + imp::spawn_child(self, handle) + .map(|spawned_child| Child { + child: spawned_child.child, + stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }), + stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }), + stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }), kill_on_drop: true, }) } @@ -353,7 +359,7 @@ impl CommandExt for Command { let inner = self.spawn_async_with_handle(handle) .into_future() - .and_then(|c| c.wait_with_output()); + .and_then(Child::wait_with_output); OutputAsync { inner: Box::new(inner), @@ -445,9 +451,9 @@ impl Child { WaitWithOutput { inner: Box::new(self.join3(stdout, stderr).map(|(status, stdout, stderr)| { Output { - status: status, - stdout: stdout, - stderr: stderr, + status, + stdout, + stderr, } })) } diff --git a/src/unix/mod.rs b/src/unix/mod.rs index 4743bf587..6ceeaaeda 100644 --- a/src/unix/mod.rs +++ b/src/unix/mod.rs @@ -38,6 +38,7 @@ use std::fmt; use std::io; use std::os::unix::io::{AsRawFd, RawFd}; use std::process::{self, ExitStatus}; +use super::SpawnedChild; use tokio_io::IoFuture; use tokio_reactor::{Handle, PollEvented}; @@ -66,21 +67,24 @@ impl fmt::Debug for Child { } } +pub(crate) fn spawn_child(cmd: &mut process::Command, handle: &Handle) -> io::Result { + let mut child = cmd.spawn()?; + let stdin = stdio(child.stdin.take(), handle)?; + let stdout = stdio(child.stdout.take(), handle)?; + let stderr = stdio(child.stderr.take(), handle)?; + + let signal = Signal::with_handle(libc::SIGCHLD, handle).flatten_stream(); + Ok(SpawnedChild { + child: Child { + inner: Reaper::new(child, signal), + }, + stdin, + stdout, + stderr, + }) +} + impl Child { - pub fn new(mut inner: process::Child, handle: &Handle) - -> io::Result<(Child, Option, Option, Option)> - { - let stdin = stdio(inner.stdin.take(), handle)?; - let stdout = stdio(inner.stdout.take(), handle)?; - let stderr = stdio(inner.stderr.take(), handle)?; - - let signal = Signal::with_handle(libc::SIGCHLD, handle).flatten_stream(); - let child = Child { - inner: Reaper::new(inner, signal), - }; - - Ok((child, stdin, stdout, stderr)) - } pub fn id(&self) -> u32 { self.inner.id() diff --git a/src/unix/reap.rs b/src/unix/reap.rs index 2326c650b..c17ac21ab 100644 --- a/src/unix/reap.rs +++ b/src/unix/reap.rs @@ -124,7 +124,7 @@ mod test { impl Wait for MockWait { fn try_wait(&mut self) -> io::Result> { let ret = if self.num_wait_until_status == self.total_waits { - Some(self.status.clone()) + Some(self.status) } else { None }; @@ -171,7 +171,7 @@ mod test { #[test] fn reaper() { let exit = ExitStatus::from_raw(0); - let mock = MockWait::new(exit.clone(), 3); + let mock = MockWait::new(exit, 3); let mut grim = Reaper::new(mock, MockStream::new(vec!( None, Some(()), diff --git a/src/windows.rs b/src/windows.rs index 9fa5bdfe1..a4f50f358 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -23,6 +23,7 @@ use std::io; use std::os::windows::prelude::*; use std::os::windows::process::ExitStatusExt; use std::process::{self, ExitStatus}; +use std::ptr; use futures::future::Fuse; use futures::sync::oneshot; @@ -36,6 +37,7 @@ use self::winapi::um::synchapi::*; use self::winapi::um::threadpoollegacyapiset::*; use self::winapi::um::winbase::*; use self::winapi::um::winnt::*; +use super::SpawnedChild; use tokio_reactor::{Handle, PollEvented}; #[must_use = "futures do nothing unless polled"] @@ -63,22 +65,24 @@ struct Waiting { unsafe impl Sync for Waiting {} unsafe impl Send for Waiting {} -impl Child { - pub fn new(mut inner: process::Child, handle: &Handle) - -> io::Result<(Child, Option, Option, Option)> - { - let stdin = stdio(inner.stdin.take(), handle)?; - let stdout = stdio(inner.stdout.take(), handle)?; - let stderr = stdio(inner.stderr.take(), handle)?; +pub(crate) fn spawn_child(cmd: &mut process::Command, handle: &Handle) -> io::Result { + let mut child = cmd.spawn()?; + let stdin = stdio(child.stdin.take(), handle)?; + let stdout = stdio(child.stdout.take(), handle)?; + let stderr = stdio(child.stderr.take(), handle)?; - let child = Child { - child: inner, + Ok(SpawnedChild { + child: Child { + child, waiting: None, - }; - - Ok((child, stdin, stdout, stderr)) - } + }, + stdin, + stdout, + stderr, + }) +} +impl Child { pub fn id(&self) -> u32 { self.child.id() } @@ -103,7 +107,7 @@ impl Child { } let (tx, rx) = oneshot::channel(); let ptr = Box::into_raw(Box::new(Some(tx))); - let mut wait_object = 0 as *mut _; + let mut wait_object = ptr::null_mut(); let rc = unsafe { RegisterWaitForSingleObject(&mut wait_object, self.child.as_raw_handle(), @@ -120,7 +124,7 @@ impl Child { } self.waiting = Some(Waiting { rx: rx.fuse(), - wait_object: wait_object, + wait_object, tx: ptr, }); } @@ -142,7 +146,7 @@ impl Drop for Waiting { unsafe extern "system" fn callback(ptr: PVOID, _timer_fired: BOOLEAN) { let complete = &mut *(ptr as *mut Option>); - drop(complete.take().unwrap().send(())); + let _ = complete.take().unwrap().send(()); } pub fn try_wait(child: &process::Child) -> io::Result> { diff --git a/tests/issue_42.rs b/tests/issue_42.rs index 0bc55b621..a0a9700c2 100644 --- a/tests/issue_42.rs +++ b/tests/issue_42.rs @@ -16,7 +16,7 @@ fn run_test() { let finished_clone = finished.clone(); thread::spawn(move || { - let _ = stream::iter_ok((0..2).into_iter()) + let _ = stream::iter_ok(0..2) .map(|i| Command::new("echo") .arg(format!("I am spawned process #{}", i)) .stdin(Stdio::null()) diff --git a/tests/stdio.rs b/tests/stdio.rs index abb00d416..38f48d5ec 100644 --- a/tests/stdio.rs +++ b/tests/stdio.rs @@ -36,7 +36,7 @@ fn feed_cat(mut cat: Child, n: usize) -> Box= n; debug!("starting read from child");