Hi,
I'm a little stuck with some example application:
I want to start another rust executable in a subprocess and communicate with it using stdin/stdout.
basically just a small echo server...where I send some command to the subprocess, do some work, let the subprocess send a response back a.s.o.
In my current setup, I have problems both on the "server" part and the "client" part. Would appreciate some tips
I pasted the full code, project can be found here: https://github.com/marcmo/process_client and https://github.com/marcmo/process_server
➜ process_server git:(master) ✗ cargo run
Compiling process_server v0.1.0 (/Users/muellero/dev/git/process_server)
Finished dev [unoptimized + debuginfo] target(s) in 0.69s
Running `target/debug/process_server`
SERVER DEBUG - Hello, world!
SERVER DEBUG - sending command: test
SERVER DEBUG - got communicator
CLIENT DEBUG - process_client args: ["../process_client/target/debug/process_client", "arg1", "arg2"]
CLIENT DEBUG - [0] received line: "test"
CLIENT DEBUG - [1] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [2] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [3] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [4] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [5] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [6] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [7] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [8] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [9] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - [10] received line: ""
CLIENT DEBUG - stdin input had len 0...
CLIENT DEBUG - exiting after 10 retries
SERVER DEBUG - called communicate
SERVER DEBUG - SERVER out: response
response
response
response
response
response
response
response
response
response
SERVER DEBUG - child process exited with: Exited(0)
this is what the server-part looks like:
use env_logger::{Builder, Target};
use log::*;
use std::io::Write;
use subprocess::{Popen, PopenConfig, Redirection};
#[cfg(target_os = "windows")]
static CLIENT_PATH: &str = "..\\process_client\\target\\debug\\process_client.exe";
#[cfg(not(target_os = "windows"))]
static CLIENT_PATH: &str = "../process_client/target/debug/process_client";
fn main() -> Result<(), std::io::Error> {
let mut builder = Builder::new();
builder
.format(|buf, record| writeln!(buf, "SERVER {} - {}", record.level(), record.args()))
.target(Target::Stderr)
.filter(None, LevelFilter::Debug)
.init();
debug!("Hello, world!");
let mut p = Popen::create(
&[CLIENT_PATH, "arg1", "arg2"],
PopenConfig {
stdout: Redirection::Pipe,
stdin: Redirection::Pipe,
..Default::default()
},
)
.unwrap();
let commands = vec!["test", "exit"];
for command in commands {
debug!("sending command: {}", command);
let mut communicator = p.communicate_start(Some(command.as_bytes().to_vec()));
debug!("got communicator");
if let Ok((out, err)) = communicator.read() {
debug!("called communicate");
if let Some(out) = out {
debug!("SERVER out: {}", String::from_utf8_lossy(&out));
}
if let Some(err) = err {
debug!("SERVER err: {}", String::from_utf8_lossy(&err));
}
}
if let Some(exit_status) = p.poll() {
debug!("child process exited with: {:?}", exit_status);
break;
}
}
p.terminate()
}
and this is the client part:
use env_logger::{Builder, Target};
use log::*;
use std::env;
use std::io;
use std::io::{Read, Write};
use std::thread;
use std::time::Duration;
fn main() -> Result<(), io::Error> {
let mut builder = Builder::new();
builder
.format(|buf, record| writeln!(buf, "CLIENT {} - {}", record.level(), record.args()))
.target(Target::Stderr)
.filter(None, LevelFilter::Debug)
.init();
let args: Vec<String> = env::args().collect();
debug!("process_client args: {:?}", args);
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut line = String::new();
let mut count = 0usize;
loop {
let n = stdin.read_line(&mut line).expect("read_to_string failed");
debug!("[{}] received line: \"{}\"", count, line);
if line == "exit" {
debug!("exiting!");
break;
}
if n == 0 {
debug!("stdin input had len 0...");
if count >= 10 {
debug!("exiting after {} retries", count);
break;
}
}
// Write the line to stdout.
stdout
.write_all(b"response\n")
.expect("writing to stdout failed");
stdout.flush().unwrap();
line.clear();
count += 1;
thread::sleep(Duration::from_millis(500));
}
Ok(())
}