tokio_process/
lib.rs

1//! An implementation of asynchronous process management for Tokio.
2//!
3//! > This crate has been **deprecated in tokio 0.2.x** and has been moved into
4//! > [`tokio::process`] behind the `process` [feature flag].
5//!
6//! [`tokio::process`]: https://docs.rs/tokio/latest/tokio/process/index.html
7//! [feature flag]: https://docs.rs/tokio/latest/tokio/index.html#feature-flags
8//!
9//! This crate provides a `CommandExt` trait to enhance the functionality of the
10//! `Command` type in the standard library. The three methods provided by this
11//! trait mirror the "spawning" methods in the standard library. The
12//! `CommandExt` trait in this crate, though, returns "future aware" types that
13//! interoperate with Tokio. The asynchronous process support is provided
14//! through signal handling on Unix and system APIs on Windows.
15//!
16//! # Examples
17//!
18//! Here's an example program which will spawn `echo hello world` and then wait
19//! for it using an event loop.
20//!
21//! ```no_run
22//! extern crate futures;
23//! extern crate tokio;
24//! extern crate tokio_process;
25//!
26//! use std::process::Command;
27//!
28//! use futures::Future;
29//! use tokio_process::CommandExt;
30//!
31//! fn main() {
32//!     // Use the standard library's `Command` type to build a process and
33//!     // then execute it via the `CommandExt` trait.
34//!     let child = Command::new("echo").arg("hello").arg("world")
35//!                         .spawn_async();
36//!
37//!     // Make sure our child succeeded in spawning and process the result
38//!     let future = child.expect("failed to spawn")
39//!         .map(|status| println!("exit status: {}", status))
40//!         .map_err(|e| panic!("failed to wait for exit: {}", e));
41//!
42//!     // Send the future to the tokio runtime for execution
43//!     tokio::run(future)
44//! }
45//! ```
46//!
47//! Next, let's take a look at an example where we not only spawn `echo hello
48//! world` but we also capture its output.
49//!
50//! ```no_run
51//! extern crate futures;
52//! extern crate tokio;
53//! extern crate tokio_process;
54//!
55//! use std::process::Command;
56//!
57//! use futures::Future;
58//! use tokio_process::CommandExt;
59//!
60//! fn main() {
61//!     // Like above, but use `output_async` which returns a future instead of
62//!     // immediately returning the `Child`.
63//!     let output = Command::new("echo").arg("hello").arg("world")
64//!                         .output_async();
65//!
66//!     let future = output.map_err(|e| panic!("failed to collect output: {}", e))
67//!         .map(|output| {
68//!             assert!(output.status.success());
69//!             assert_eq!(output.stdout, b"hello world\n");
70//!         });
71//!
72//!     tokio::run(future);
73//! }
74//! ```
75//!
76//! We can also read input line by line.
77//!
78//! ```no_run
79//! extern crate failure;
80//! extern crate futures;
81//! extern crate tokio;
82//! extern crate tokio_process;
83//! extern crate tokio_io;
84//!
85//! use failure::Error;
86//! use futures::{Future, Stream};
87//! use std::io::BufReader;
88//! use std::process::{Command, Stdio};
89//! use tokio_process::{Child, ChildStdout, CommandExt};
90//!
91//! fn lines_stream(child: &mut Child) -> impl Stream<Item = String, Error = Error> + Send + 'static {
92//!     let stdout = child.stdout().take()
93//!         .expect("child did not have a handle to stdout");
94//!
95//!     tokio_io::io::lines(BufReader::new(stdout))
96//!         // Convert any io::Error into a failure::Error for better flexibility
97//!         .map_err(|e| Error::from(e))
98//!         // We print each line we've received here as an example of a way we can
99//!         // do something with the data. This can be changed to map the data to
100//!         // something else, or to consume it differently.
101//!         .inspect(|line| println!("Line: {}", line))
102//! }
103//!
104//! fn main() {
105//!     // Lazily invoke any code so it can run directly within the tokio runtime
106//!     tokio::run(futures::lazy(|| {
107//!         let mut cmd = Command::new("cat");
108//!
109//!         // Specify that we want the command's standard output piped back to us.
110//!         // By default, standard input/output/error will be inherited from the
111//!         // current process (for example, this means that standard input will
112//!         // come from the keyboard and standard output/error will go directly to
113//!         // the terminal if this process is invoked from the command line).
114//!         cmd.stdout(Stdio::piped());
115//!
116//!         let mut child = cmd.spawn_async()
117//!             .expect("failed to spawn command");
118//!
119//!         let lines = lines_stream(&mut child);
120//!
121//!         // Spawning into the tokio runtime requires that the future's Item and
122//!         // Error are both `()`. This is because tokio doesn't know what to do
123//!         // with any results or errors, so it requires that we've handled them!
124//!         //
125//!         // We can replace these sample usages of the child's exit status (or
126//!         // an encountered error) perform some different actions if needed!
127//!         // For example, log the error, or send a message on a channel, etc.
128//!         let child_future = child
129//!                 .map(|status| println!("child status was: {}", status))
130//!                 .map_err(|e| panic!("error while running child: {}", e));
131//!
132//!         // Ensure the child process can live on within the runtime, otherwise
133//!         // the process will get killed if this handle is dropped
134//!         tokio::spawn(child_future);
135//!
136//!         // Return a future to tokio. This is the same as calling using
137//!         // `tokio::spawn` above, but without having to return a dummy future
138//!         // here.
139//!         lines
140//!             // Convert the stream of values into a future which will resolve
141//!             // once the entire stream has been consumed. In this example we
142//!             // don't need to do anything with the data within the `for_each`
143//!             // call, but you can extend this to do something else (keep in mind
144//!             // that the stream will not produce items until the future returned
145//!             // from the closure resolves).
146//!             .for_each(|_| Ok(()))
147//!             // Similarly we "handle" any errors that arise, as required by tokio.
148//!             .map_err(|e| panic!("error while processing lines: {}", e))
149//!     }));
150//! }
151//! ```
152//!
153//! # Caveats
154//!
155//! While similar to the standard library, this crate's `Child` type differs
156//! importantly in the behavior of `drop`. In the standard library, a child
157//! process will continue running after the instance of `std::process::Child`
158//! is dropped. In this crate, however, because `tokio_process::Child` is a
159//! future of the child's `ExitStatus`, a child process is terminated if
160//! `tokio_process::Child` is dropped. The behavior of the standard library can
161//! be regained with the `Child::forget` method.
162
163#![warn(missing_debug_implementations)]
164#![deny(missing_docs)]
165#![doc(html_root_url = "https://docs.rs/tokio-process/0.2")]
166
167extern crate futures;
168extern crate tokio_io;
169extern crate tokio_reactor;
170
171#[cfg(unix)]
172#[macro_use]
173extern crate lazy_static;
174#[cfg(unix)]
175#[macro_use]
176extern crate log;
177
178use std::io::{self, Read, Write};
179use std::process::{Command, ExitStatus, Output, Stdio};
180
181use crate::kill::Kill;
182use futures::future::{ok, Either};
183use futures::{Async, Future, IntoFuture, Poll};
184use std::fmt;
185use tokio_io::io::read_to_end;
186use tokio_io::{AsyncRead, AsyncWrite, IoFuture};
187use tokio_reactor::Handle;
188
189#[path = "unix/mod.rs"]
190#[cfg(unix)]
191mod imp;
192
193#[path = "windows.rs"]
194#[cfg(windows)]
195mod imp;
196
197mod kill;
198
199/// Extensions provided by this crate to the `Command` type in the standard
200/// library.
201///
202/// This crate primarily enhances the standard library's `Command` type with
203/// asynchronous capabilities. The currently three blocking functions in the
204/// standard library, `spawn`, `status`, and `output`, all have asynchronous
205/// versions through this trait.
206///
207/// Note that the `Child` type spawned is specific to this crate, and that the
208/// I/O handles created from this crate are all asynchronous as well (differing
209/// from their `std` counterparts).
210pub trait CommandExt {
211    /// Executes the command as a child process, returning a handle to it.
212    ///
213    /// By default, stdin, stdout and stderr are inherited from the parent.
214    ///
215    /// This method will spawn the child process synchronously and return a
216    /// handle to a future-aware child process. The `Child` returned implements
217    /// `Future` itself to acquire the `ExitStatus` of the child, and otherwise
218    /// the `Child` has methods to acquire handles to the stdin, stdout, and
219    /// stderr streams.
220    ///
221    /// All I/O this child does will be associated with the current default
222    /// event loop.
223    fn spawn_async(&mut self) -> io::Result<Child> {
224        self.spawn_async_with_handle(&Handle::default())
225    }
226
227    /// Executes the command as a child process, returning a handle to it.
228    ///
229    /// By default, stdin, stdout and stderr are inherited from the parent.
230    ///
231    /// This method will spawn the child process synchronously and return a
232    /// handle to a future-aware child process. The `Child` returned implements
233    /// `Future` itself to acquire the `ExitStatus` of the child, and otherwise
234    /// the `Child` has methods to acquire handles to the stdin, stdout, and
235    /// stderr streams.
236    ///
237    /// The `handle` specified to this method must be a handle to a valid event
238    /// loop, and all I/O this child does will be associated with the specified
239    /// event loop.
240    fn spawn_async_with_handle(&mut self, handle: &Handle) -> io::Result<Child>;
241
242    /// Executes a command as a child process, waiting for it to finish and
243    /// collecting its exit status.
244    ///
245    /// By default, stdin, stdout and stderr are inherited from the parent.
246    ///
247    /// The `StatusAsync` future returned will resolve to the `ExitStatus`
248    /// type in the standard library representing how the process exited. If
249    /// any input/output handles are set to a pipe then they will be immediately
250    ///  closed after the child is spawned.
251    ///
252    /// All I/O this child does will be associated with the current default
253    /// event loop.
254    ///
255    /// If the `StatusAsync` future is dropped before the future resolves, then
256    /// the child will be killed, if it was spawned.
257    ///
258    /// # Errors
259    ///
260    /// This function will return an error immediately if the child process
261    /// cannot be spawned. Otherwise errors obtained while waiting for the child
262    /// are returned through the `StatusAsync` future.
263    fn status_async(&mut self) -> io::Result<StatusAsync> {
264        self.status_async_with_handle(&Handle::default())
265    }
266
267    /// Executes a command as a child process, waiting for it to finish and
268    /// collecting its exit status.
269    ///
270    /// By default, stdin, stdout and stderr are inherited from the parent.
271    ///
272    /// The `StatusAsync` future returned will resolve to the `ExitStatus`
273    /// type in the standard library representing how the process exited. If
274    /// any input/output handles are set to a pipe then they will be immediately
275    ///  closed after the child is spawned.
276    ///
277    /// The `handle` specified must be a handle to a valid event loop, and all
278    /// I/O this child does will be associated with the specified event loop.
279    ///
280    /// If the `StatusAsync` future is dropped before the future resolves, then
281    /// the child will be killed, if it was spawned.
282    ///
283    /// # Errors
284    ///
285    /// This function will return an error immediately if the child process
286    /// cannot be spawned. Otherwise errors obtained while waiting for the child
287    /// are returned through the `StatusAsync` future.
288    fn status_async_with_handle(&mut self, handle: &Handle) -> io::Result<StatusAsync>;
289
290    /// Executes the command as a child process, waiting for it to finish and
291    /// collecting all of its output.
292    ///
293    /// > **Note**: this method, unlike the standard library, will
294    /// > unconditionally configure the stdout/stderr handles to be pipes, even
295    /// > if they have been previously configured. If this is not desired then
296    /// > the `spawn_async` method should be used in combination with the
297    /// > `wait_with_output` method on child.
298    ///
299    /// This method will return a future representing the collection of the
300    /// child process's stdout/stderr. The `OutputAsync` future will resolve to
301    /// the `Output` type in the standard library, containing `stdout` and
302    /// `stderr` as `Vec<u8>` along with an `ExitStatus` representing how the
303    /// process exited.
304    ///
305    /// All I/O this child does will be associated with the current default
306    /// event loop.
307    ///
308    /// If the `OutputAsync` future is dropped before the future resolves, then
309    /// the child will be killed, if it was spawned.
310    fn output_async(&mut self) -> OutputAsync {
311        self.output_async_with_handle(&Handle::default())
312    }
313
314    /// Executes the command as a child process, waiting for it to finish and
315    /// collecting all of its output.
316    ///
317    /// > **Note**: this method, unlike the standard library, will
318    /// > unconditionally configure the stdout/stderr handles to be pipes, even
319    /// > if they have been previously configured. If this is not desired then
320    /// > the `spawn_async` method should be used in combination with the
321    /// > `wait_with_output` method on child.
322    ///
323    /// This method will return a future representing the collection of the
324    /// child process's stdout/stderr. The `OutputAsync` future will resolve to
325    /// the `Output` type in the standard library, containing `stdout` and
326    /// `stderr` as `Vec<u8>` along with an `ExitStatus` representing how the
327    /// process exited.
328    ///
329    /// The `handle` specified must be a handle to a valid event loop, and all
330    /// I/O this child does will be associated with the specified event loop.
331    ///
332    /// If the `OutputAsync` future is dropped before the future resolves, then
333    /// the child will be killed, if it was spawned.
334    fn output_async_with_handle(&mut self, handle: &Handle) -> OutputAsync;
335}
336
337struct SpawnedChild {
338    child: imp::Child,
339    stdin: Option<imp::ChildStdin>,
340    stdout: Option<imp::ChildStdout>,
341    stderr: Option<imp::ChildStderr>,
342}
343
344impl CommandExt for Command {
345    fn spawn_async_with_handle(&mut self, handle: &Handle) -> io::Result<Child> {
346        imp::spawn_child(self, handle).map(|spawned_child| Child {
347            child: ChildDropGuard::new(spawned_child.child),
348            stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }),
349            stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }),
350            stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }),
351        })
352    }
353
354    fn status_async_with_handle(&mut self, handle: &Handle) -> io::Result<StatusAsync> {
355        self.spawn_async_with_handle(handle).map(|mut child| {
356            // Ensure we close any stdio handles so we can't deadlock
357            // waiting on the child which may be waiting to read/write
358            // to a pipe we're holding.
359            child.stdin.take();
360            child.stdout.take();
361            child.stderr.take();
362
363            StatusAsync { inner: child }
364        })
365    }
366
367    fn output_async_with_handle(&mut self, handle: &Handle) -> OutputAsync {
368        self.stdout(Stdio::piped());
369        self.stderr(Stdio::piped());
370
371        let inner = self
372            .spawn_async_with_handle(handle)
373            .into_future()
374            .and_then(Child::wait_with_output);
375
376        OutputAsync {
377            inner: Box::new(inner),
378        }
379    }
380}
381
382/// A drop guard which ensures the child process is killed on drop to maintain
383/// the contract of dropping a Future leads to "cancellation".
384#[derive(Debug)]
385struct ChildDropGuard<T: Kill> {
386    inner: T,
387    kill_on_drop: bool,
388}
389
390impl<T: Kill> ChildDropGuard<T> {
391    fn new(inner: T) -> Self {
392        Self {
393            inner,
394            kill_on_drop: true,
395        }
396    }
397
398    fn forget(&mut self) {
399        self.kill_on_drop = false;
400    }
401}
402
403impl<T: Kill> Kill for ChildDropGuard<T> {
404    fn kill(&mut self) -> io::Result<()> {
405        let ret = self.inner.kill();
406
407        if ret.is_ok() {
408            self.kill_on_drop = false;
409        }
410
411        ret
412    }
413}
414
415impl<T: Kill> Drop for ChildDropGuard<T> {
416    fn drop(&mut self) {
417        if self.kill_on_drop {
418            drop(self.kill());
419        }
420    }
421}
422
423impl<T: Future + Kill> Future for ChildDropGuard<T> {
424    type Item = T::Item;
425    type Error = T::Error;
426
427    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
428        let ret = self.inner.poll();
429
430        if let Ok(Async::Ready(_)) = ret {
431            // Avoid the overhead of trying to kill a reaped process
432            self.kill_on_drop = false;
433        }
434
435        ret
436    }
437}
438
439/// Representation of a child process spawned onto an event loop.
440///
441/// This type is also a future which will yield the `ExitStatus` of the
442/// underlying child process. A `Child` here also provides access to information
443/// like the OS-assigned identifier and the stdio streams.
444///
445/// > **Note**: The behavior of `drop` on a child in this crate is *different
446/// > than the behavior of the standard library*. If a `tokio_process::Child` is
447/// > dropped before the process finishes then the process will be terminated.
448/// > In the standard library, however, the process continues executing. This is
449/// > done because futures in general take `drop` as a sign of cancellation, and
450/// > this `Child` is itself a future. If you'd like to run a process in the
451/// > background, though, you may use the `forget` method.
452#[must_use = "futures do nothing unless polled"]
453#[derive(Debug)]
454pub struct Child {
455    child: ChildDropGuard<imp::Child>,
456    stdin: Option<ChildStdin>,
457    stdout: Option<ChildStdout>,
458    stderr: Option<ChildStderr>,
459}
460
461impl Child {
462    /// Returns the OS-assigned process identifier associated with this child.
463    pub fn id(&self) -> u32 {
464        self.child.inner.id()
465    }
466
467    /// Forces the child to exit.
468    ///
469    /// This is equivalent to sending a SIGKILL on unix platforms.
470    pub fn kill(&mut self) -> io::Result<()> {
471        self.child.kill()
472    }
473
474    /// Returns a handle for writing to the child's stdin, if it has been
475    /// captured
476    pub fn stdin(&mut self) -> &mut Option<ChildStdin> {
477        &mut self.stdin
478    }
479
480    /// Returns a handle for writing to the child's stdout, if it has been
481    /// captured
482    pub fn stdout(&mut self) -> &mut Option<ChildStdout> {
483        &mut self.stdout
484    }
485
486    /// Returns a handle for writing to the child's stderr, if it has been
487    /// captured
488    pub fn stderr(&mut self) -> &mut Option<ChildStderr> {
489        &mut self.stderr
490    }
491
492    /// Returns a future that will resolve to an `Output`, containing the exit
493    /// status, stdout, and stderr of the child process.
494    ///
495    /// The returned future will simultaneously waits for the child to exit and
496    /// collect all remaining output on the stdout/stderr handles, returning an
497    /// `Output` instance.
498    ///
499    /// The stdin handle to the child process, if any, will be closed before
500    /// waiting. This helps avoid deadlock: it ensures that the child does not
501    /// block waiting for input from the parent, while the parent waits for the
502    /// child to exit.
503    ///
504    /// By default, stdin, stdout and stderr are inherited from the parent. In
505    /// order to capture the output into this `Output` it is necessary to create
506    /// new pipes between parent and child. Use `stdout(Stdio::piped())` or
507    /// `stderr(Stdio::piped())`, respectively, when creating a `Command`.
508    pub fn wait_with_output(mut self) -> WaitWithOutput {
509        drop(self.stdin().take());
510        let stdout = match self.stdout().take() {
511            Some(io) => Either::A(read_to_end(io, Vec::new()).map(|p| p.1)),
512            None => Either::B(ok(Vec::new())),
513        };
514        let stderr = match self.stderr().take() {
515            Some(io) => Either::A(read_to_end(io, Vec::new()).map(|p| p.1)),
516            None => Either::B(ok(Vec::new())),
517        };
518
519        WaitWithOutput {
520            inner: Box::new(
521                self.join3(stdout, stderr)
522                    .map(|(status, stdout, stderr)| Output {
523                        status,
524                        stdout,
525                        stderr,
526                    }),
527            ),
528        }
529    }
530
531    /// Drop this `Child` without killing the underlying process.
532    ///
533    /// Normally a `Child` is killed if it's still alive when dropped, but this
534    /// method will ensure that the child may continue running once the `Child`
535    /// instance is dropped.
536    ///
537    /// > **Note**: this method may leak OS resources depending on your platform.
538    /// > To ensure resources are eventually cleaned up, consider sending the
539    /// > `Child` instance into an event loop as an alternative to this method.
540    ///
541    /// ```no_run
542    /// # extern crate futures;
543    /// # extern crate tokio;
544    /// # extern crate tokio_process;
545    /// #
546    /// # use std::process::Command;
547    /// #
548    /// # use futures::Future;
549    /// # use tokio_process::CommandExt;
550    /// #
551    /// # fn main() {
552    /// let child = Command::new("echo").arg("hello").arg("world")
553    ///                     .spawn_async()
554    ///                     .expect("failed to spawn");
555    ///
556    /// let do_cleanup = child.map(|_| ()) // Ignore result
557    ///                       .map_err(|_| ()); // Ignore errors
558    ///
559    /// tokio::spawn(do_cleanup);
560    /// # }
561    /// ```
562    pub fn forget(mut self) {
563        self.child.forget();
564    }
565}
566
567impl Future for Child {
568    type Item = ExitStatus;
569    type Error = io::Error;
570
571    fn poll(&mut self) -> Poll<ExitStatus, io::Error> {
572        self.child.poll()
573    }
574}
575
576/// Future returned from the `Child::wait_with_output` method.
577///
578/// This future will resolve to the standard library's `Output` type which
579/// contains the exit status, stdout, and stderr of a child process.
580#[must_use = "futures do nothing unless polled"]
581pub struct WaitWithOutput {
582    inner: IoFuture<Output>,
583}
584
585impl fmt::Debug for WaitWithOutput {
586    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
587        fmt.debug_struct("WaitWithOutput")
588            .field("inner", &"..")
589            .finish()
590    }
591}
592
593impl Future for WaitWithOutput {
594    type Item = Output;
595    type Error = io::Error;
596
597    fn poll(&mut self) -> Poll<Output, io::Error> {
598        self.inner.poll()
599    }
600}
601
602#[doc(hidden)]
603#[deprecated(note = "renamed to `StatusAsync`", since = "0.2.1")]
604pub type StatusAsync2 = StatusAsync;
605
606/// Future returned by the `CommandExt::status_async` method.
607///
608/// This future is used to conveniently spawn a child and simply wait for its
609/// exit status. This future will resolves to the `ExitStatus` type in the
610/// standard library.
611#[must_use = "futures do nothing unless polled"]
612#[derive(Debug)]
613pub struct StatusAsync {
614    inner: Child,
615}
616
617impl Future for StatusAsync {
618    type Item = ExitStatus;
619    type Error = io::Error;
620
621    fn poll(&mut self) -> Poll<ExitStatus, io::Error> {
622        self.inner.poll()
623    }
624}
625
626/// Future returned by the `CommandExt::output_async` method.
627///
628/// This future is mostly equivalent to spawning a process and then calling
629/// `wait_with_output` on it internally. This can be useful to simply spawn a
630/// process, collecting all of its output and its exit status.
631#[must_use = "futures do nothing unless polled"]
632pub struct OutputAsync {
633    inner: IoFuture<Output>,
634}
635
636impl fmt::Debug for OutputAsync {
637    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
638        fmt.debug_struct("OutputAsync")
639            .field("inner", &"..")
640            .finish()
641    }
642}
643
644impl Future for OutputAsync {
645    type Item = Output;
646    type Error = io::Error;
647
648    fn poll(&mut self) -> Poll<Output, io::Error> {
649        self.inner.poll()
650    }
651}
652
653/// The standard input stream for spawned children.
654///
655/// This type implements the `Write` trait to pass data to the stdin handle of
656/// a child process. Note that this type is also "futures aware" meaning that it
657/// is both (a) nonblocking and (b) will panic if used off of a future's task.
658#[derive(Debug)]
659pub struct ChildStdin {
660    inner: imp::ChildStdin,
661}
662
663/// The standard output stream for spawned children.
664///
665/// This type implements the `Read` trait to read data from the stdout handle
666/// of a child process. Note that this type is also "futures aware" meaning
667/// that it is both (a) nonblocking and (b) will panic if used off of a
668/// future's task.
669#[derive(Debug)]
670pub struct ChildStdout {
671    inner: imp::ChildStdout,
672}
673
674/// The standard error stream for spawned children.
675///
676/// This type implements the `Read` trait to read data from the stderr handle
677/// of a child process. Note that this type is also "futures aware" meaning
678/// that it is both (a) nonblocking and (b) will panic if used off of a
679/// future's task.
680#[derive(Debug)]
681pub struct ChildStderr {
682    inner: imp::ChildStderr,
683}
684
685impl Write for ChildStdin {
686    fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
687        self.inner.write(bytes)
688    }
689
690    fn flush(&mut self) -> io::Result<()> {
691        self.inner.flush()
692    }
693}
694
695impl AsyncWrite for ChildStdin {
696    fn shutdown(&mut self) -> Poll<(), io::Error> {
697        self.inner.shutdown()
698    }
699}
700
701impl Read for ChildStdout {
702    fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
703        self.inner.read(bytes)
704    }
705}
706
707impl AsyncRead for ChildStdout {}
708
709impl Read for ChildStderr {
710    fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> {
711        self.inner.read(bytes)
712    }
713}
714
715impl AsyncRead for ChildStderr {}
716
717#[cfg(unix)]
718mod sys {
719    use super::{ChildStderr, ChildStdin, ChildStdout};
720    use std::os::unix::io::{AsRawFd, RawFd};
721
722    impl AsRawFd for ChildStdin {
723        fn as_raw_fd(&self) -> RawFd {
724            self.inner.get_ref().as_raw_fd()
725        }
726    }
727
728    impl AsRawFd for ChildStdout {
729        fn as_raw_fd(&self) -> RawFd {
730            self.inner.get_ref().as_raw_fd()
731        }
732    }
733
734    impl AsRawFd for ChildStderr {
735        fn as_raw_fd(&self) -> RawFd {
736            self.inner.get_ref().as_raw_fd()
737        }
738    }
739}
740
741#[cfg(windows)]
742mod sys {
743    use super::{ChildStderr, ChildStdin, ChildStdout};
744    use std::os::windows::io::{AsRawHandle, RawHandle};
745
746    impl AsRawHandle for ChildStdin {
747        fn as_raw_handle(&self) -> RawHandle {
748            self.inner.get_ref().as_raw_handle()
749        }
750    }
751
752    impl AsRawHandle for ChildStdout {
753        fn as_raw_handle(&self) -> RawHandle {
754            self.inner.get_ref().as_raw_handle()
755        }
756    }
757
758    impl AsRawHandle for ChildStderr {
759        fn as_raw_handle(&self) -> RawHandle {
760            self.inner.get_ref().as_raw_handle()
761        }
762    }
763}
764
765#[cfg(test)]
766mod test {
767    use super::ChildDropGuard;
768    use crate::kill::Kill;
769    use futures::{Async, Future, Poll};
770    use std::io;
771
772    struct Mock {
773        num_kills: usize,
774        num_polls: usize,
775        poll_result: Poll<(), ()>,
776    }
777
778    impl Mock {
779        fn new() -> Self {
780            Self::with_result(Ok(Async::NotReady))
781        }
782
783        fn with_result(result: Poll<(), ()>) -> Self {
784            Self {
785                num_kills: 0,
786                num_polls: 0,
787                poll_result: result,
788            }
789        }
790    }
791
792    impl Kill for Mock {
793        fn kill(&mut self) -> io::Result<()> {
794            self.num_kills += 1;
795            Ok(())
796        }
797    }
798
799    impl Future for Mock {
800        type Item = ();
801        type Error = ();
802
803        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
804            self.num_polls += 1;
805            self.poll_result
806        }
807    }
808
809    #[test]
810    fn kills_on_drop() {
811        let mut mock = Mock::new();
812
813        {
814            let guard = ChildDropGuard::new(&mut mock);
815            drop(guard);
816        }
817
818        assert_eq!(1, mock.num_kills);
819        assert_eq!(0, mock.num_polls);
820    }
821
822    #[test]
823    fn no_kill_if_already_killed() {
824        let mut mock = Mock::new();
825
826        {
827            let mut guard = ChildDropGuard::new(&mut mock);
828            let _ = guard.kill();
829            drop(guard);
830        }
831
832        assert_eq!(1, mock.num_kills);
833        assert_eq!(0, mock.num_polls);
834    }
835
836    #[test]
837    fn no_kill_if_reaped() {
838        let mut mock_pending = Mock::with_result(Ok(Async::NotReady));
839        let mut mock_reaped = Mock::with_result(Ok(Async::Ready(())));
840        let mut mock_err = Mock::with_result(Err(()));
841
842        {
843            let mut guard = ChildDropGuard::new(&mut mock_pending);
844            let _ = guard.poll();
845
846            let mut guard = ChildDropGuard::new(&mut mock_reaped);
847            let _ = guard.poll();
848
849            let mut guard = ChildDropGuard::new(&mut mock_err);
850            let _ = guard.poll();
851        }
852
853        assert_eq!(1, mock_pending.num_kills);
854        assert_eq!(1, mock_pending.num_polls);
855
856        assert_eq!(0, mock_reaped.num_kills);
857        assert_eq!(1, mock_reaped.num_polls);
858
859        assert_eq!(1, mock_err.num_kills);
860        assert_eq!(1, mock_err.num_polls);
861    }
862
863    #[test]
864    fn no_kill_on_forget() {
865        let mut mock = Mock::new();
866
867        {
868            let mut guard = ChildDropGuard::new(&mut mock);
869            guard.forget();
870            drop(guard);
871        }
872
873        assert_eq!(0, mock.num_kills);
874        assert_eq!(0, mock.num_polls);
875    }
876}