For some reason, I am unable to read from the child process stderr
the second time. Here is what I do.
I am spawning a child process for cucumber tests. In the first step I spawn the process, take its stderr
, save it, and then read from it. Here is the code:
pub fn wait_process_output(
reader: &mut BufReader<ChildStderr>,
output: Vec<(String, u16)>,
) -> Result<(), String> {
let mut process_output = String::new();
loop {
match reader.read_line(&mut process_output) {
Err(e) => {
return Err(format!("Unable to read output: {}", e));
}
Ok(_) => {
// processing here
}
};
}
}
pub fn step1(world: &mut TestWorld) {
world.app_handler = Some(
Command::new(&world.app_bin)
.stderr(Stdio::piped())
.spawn()
.unwrap(),
);
let app_stderr = world.app_handler.as_mut().unwrap().stderr.take().unwrap();
world.app_reader = Some(BufReader::new(app_stderr));
wait_process_output(world.app_reader.as_mut().unwrap(), /* expected data */).ok();
}
This code works correctly: stderr
is being read as expected.
In the third test step, I try to read process output one more time:
pub fn step3(world: &mut TestWorld) {
wait_process_output(world.app_reader.as_mut().unwrap(), /* expected data */).ok();
}
This time reader.read_line
hangs infinitely: nothing is being read. I am sure the child process produces some output: I can see it if I run it within the same conditions separately.
Could you please suggest any ideas why the BufReader
object becomes corrupted when I try to read from it the second time?
I got to the solution. The issue was that app
produced an output earlier than step3
started to read it. I thought that there is some kind of buffer implemented for this kind of situation but it seems I was wrong. So I finally used the following two methods to solve my issue:
pub fn wait_process_output(
receiver: &Receiver<String>,
output: Vec<(String, u16)>,
) -> Result<(), String> {
loop {
match receiver.try_recv() {
// process output
}
}
}
pub fn start_listener(sender: Sender<String>, stream: ChildStderr) {
spawn(move || {
let mut f = BufReader::new(stream);
loop {
let mut buf = String::new();
match f.read_line(&mut buf) {
Ok(_) => {
sender.send(buf).unwrap();
continue;
}
Err(e) => {
println!("Unable to read process stderr: {:?}", e);
break;
}
}
}
});
}