2017-10-22 7 views
2

長時間実行している子プロセスがあり、多くのデータを読み書きする必要があります。作家が完了すると、長時間実行しているstd :: process :: Childへの読み書き

extern crate scoped_threadpool; 

fn main() { 
    // run the subprocess 
    let mut child = std::process::Command::new("cat") 
     .stdin(std::process::Stdio::piped()) 
     .stdout(std::process::Stdio::piped()) 
     .spawn() 
     .unwrap(); 

    let child_stdout = child.stdout.as_mut().unwrap(); 
    let child_stdin = std::sync::Mutex::new(child.stdin.as_mut().unwrap()); 

    let mut pool = scoped_threadpool::Pool::new(2); 
    pool.scoped(|scope| { 
     // read all output from the subprocess 
     scope.execute(move || { 
      use std::io::BufRead; 
      let reader = std::io::BufReader::new(child_stdout); 
      for line in reader.lines() { 
       println!("{}", line.unwrap()); 
      } 
     }); 

     // write to the subprocess 
     scope.execute(move || { 
      for a in 0..1000 { 
       use std::io::Write; 
       writeln!(&mut child_stdin.lock().unwrap(), "{}", a).unwrap(); 
      } // close child_stdin??? 
     }); 
    }); 
} 

読者はEOFを見ているように私は、child_stdinようにサブプロセスが終了し、終了を閉じたいと:私は、リーダー・スレッドとそれぞれchild.stdoutchild.stdinを操作ライター・スレッドを持っていますpool.scopedが返されます。私はchild.wait()なしでこれを行うことはできません。child.wait()は2つのスレッドによって借用されているため、私はchild.wait()に電話することはできません。

このプログラムを完成させるにはどうすればよいですか?

+0

あなたは子プロセスに固定された文字列を作成している場合は、[サブプロセス](https://crates.io/crates/subprocess)を検討する必要がありますこれは、あなたがスレッドでやっていることに対して、['' '' ''(https://docs.rs/subprocess/0.1.11/subprocess/struct.Popen.html#method.communicate)メソッドを実装しています。また、上記を 'let input =(0..1000).map(| i | format!(" {} "、i))と表現するビルダースタイルのAPIも公開しています。免責条項:私はサブプロセスの作者です。私はサブプロセスの作成者です。 – user4815162342

答えて

2

あなたはMutex^_ ^を使用して所有権を共有しています。 child.stdinへの参照を取る代わりに、それを完全所有してスレッドに渡します。スレッドが終了すると、それは暗黙のうちにそれを閉じる、削除されます。

let mut child_stdin = child.stdin.unwrap(); 

// ... 

scope.execute(move || 
    for a in 0..1000 { 
     use std::io::Write; 
     writeln!(&mut child_stdin, "{}", a).unwrap(); 
    } 
    // child_stdin has been moved into this closure and is now 
    // dropped, closing it. 
); 

あなたはまだstdoutへの参照との所有権の移転を変更、ExitStatusを取得するためにwaitを呼び出すことができるようにしたい場合Option::takeを使用するstdin。これは、childが全く借りていないことを意味します

let mut child = // ... 

let child_stdout = child.stdout.as_mut().unwrap(); 
let mut child_stdin = child.stdin.take().unwrap(); 

// ... 

child.wait().unwrap(); 
+0

確かに、これは動作します。残念ですが、今は 'child.wait()'と呼ぶことはできませんが、私の特定のプログラムでは必要ありません。 – njaard

+1

@njaard 'child.wait()'をどこで呼びたいのですか? – Shepmaster

+1

私は、(スコープの外で)終了した後に子プロセスの 'ExitStatus'を取得したいと思います。 – njaard

関連する問題