Hey guys,
My question is probably a duplicate. If it is please direct me to a helpful question because I don't have any idea what to look for.
I am currently developing a library which interfaces with a process via stdin. I'm storing the process handle in a struct:
pub struct Process {
process: Child,
init: bool
}
I have the following 2 functions which 'talk' to the process:
pub fn init_engine(&mut self, protocol: String, depth: String) {
let mut output = Stockfish::talk_to_engine(self, &format!("go depth {}", &depth));
print!("{}", Stockfish::parse_engine_answer(&mut output));
self.init = true;
}
fn talk_to_engine(&mut self, input: &String) -> ChildStdout {
let stdin = &mut self.process.stdin.take().unwrap();
stdin.write_all(input.as_bytes()).expect("Failed to write to process.");
match self.process.stdout.take() {
Some(x) => return x,
None => panic!("response from engine was empty")
};
}
When I call init_engine one time, I get the correct output. However, when I call it a second time, the unwrap line panic's because it's none, so I assume the whole Process.process object does not exist anymore.
Thanks for the help. I'm still a complete beginner in this language so you can kill me on that
Well, yeah haha. That was a dumb statement from me. I thought you mean an explicit newline (\n) after the commands. What I thought was weird, in the previous version of my program I would actually get output. The problem is that when I would give it multiple commands. Isn't it deadlocking?
Also, I tried adding an explicit newline after the command. It didn't do anything.
The program prints to stdout before stdin is closed. In this case you have to ensure that you read from stdout as the program will pause when the stdout kernel buffer is full. If you then try to write to it's stdin and you fill the stdin kernel buffer, you get a deadlock.
The program waits until stdin is closed before it outputs anything. In this case you have to make sure that you close stdin by dropping it. Eg self.process.stdin.take();.
Based on your first question, I assumed you were intending for some back-and-forth communication with the subprocess. If you only want to write to stdin once, then .take() is appropriate.
If you do need the back and forth communication, then you can't close stdin before you're done with it.
If it was working for a single command when you were closing stdin, then chances are you just need to call .flush() on the stdin, to ensure the data gets sent to the subprocess "now". I suspect you will also need an explicit newline, as neither the format! macro or write_all will include one for you.