title: Repeatedly read subprocess output with tokio-process
body: <p>For a GUI tool I'm writing in Rust I'd like to kick off long-lived subprocesses and then repeatedly poll them for output. I don't want to block indefinitely waiting for output from any given one, so I'm using <code>tokio</code> and <code>tokio-process</code> to run the process and timeout the output reading. I need to store the subprocess in a struct as well.</p>
  
  <p>I'm running into problems because it seems I need to consume the subprocess's output stream in order to read from it, so after a single read I'm unable to access it again.</p>
  
  <p>I've included a simplified reproduction of my problem below. It prints actual output for the first invocation of <code>print_output</code>, but then prints <code>No process_output_fut</code> for the second invocation since I had to <code>take</code> the output future out of the <code>Plugin</code> struct and consume it in order to read from it.</p>
  
  <p>Any suggestions for how to refactor this code to avoid consuming the process output future with each attempt to fetch the output?</p>
  
  <pre class="lang-rust prettyprint-override"><code>extern crate tokio;
  
  use std::process::{Command, Stdio};
  use std::time::Duration;
  
  use tokio::prelude::*;
  use tokio::codec::{FramedRead, LinesCodec};
  use tokio::prelude::stream::StreamFuture;
  use tokio::timer::Timeout;
  use tokio_process::{Child, ChildStdout, CommandExt};
  
  pub struct Plugin {
      process: Option&lt;Child&gt;,
      process_output_fut: Option&lt;Timeout&lt;StreamFuture&lt;FramedRead&lt;ChildStdout, LinesCodec&gt;&gt;&gt;&gt;,
      tokio_runtime: tokio::runtime::Runtime,
  }
  
  impl Plugin {
      pub fn new() -&gt; Self {
          return Plugin {
              process: None,
              process_output_fut: None,
              tokio_runtime: tokio::runtime::Runtime::new().expect(
                  "Could not create tokio runtime"
              ),
          }
      }
  
      pub fn spawn(&amp;mut self, arg: String) {
          let mut process = Command::new("/bin/ls")
              .arg(arg)
              .stdout(Stdio::piped())
              .spawn_async()
              .expect("Failed to spawn command");
  
          if let Some(plugin_output) = process.stdout().take() {
              let lines_codec = LinesCodec::new();
              self.process_output_fut = Some(FramedRead::new(plugin_output, lines_codec)
                  .into_future()
                  .timeout(Duration::from_millis(3000)));
          }
          self.process = Some(process);
      }
  
      pub fn print_output(&amp;mut self) {
          if let Some(process_output_fut) = self.process_output_fut.take() {
              let result = self.tokio_runtime.block_on(process_output_fut).unwrap();
              if let Some(output) = result.0 {
                      println!("{:?}", output);
              };
          } else {
              println!("No process_output_fut");
          }
      }
  }
  
  
  fn main() {
      let mut p = Plugin::new();
      p.spawn("/");
      p.print_output();
      p.print_output();
  }
  </code></pre>