diff --git a/xtask/src/run.rs b/xtask/src/run.rs index 63d33dad..c76e3e22 100644 --- a/xtask/src/run.rs +++ b/xtask/src/run.rs @@ -5,7 +5,8 @@ use std::{ fs::{copy, create_dir_all, metadata, File}, io::{BufRead as _, BufReader, ErrorKind, Write as _}, path::{Path, PathBuf}, - process::{Child, Command, Output, Stdio}, + process::{Child, ChildStdin, Command, Output, Stdio}, + sync::{Arc, Mutex}, thread, }; @@ -462,32 +463,49 @@ pub fn run(opts: Options) -> Result<()> { stderr, .. } = &mut qemu_child; - let mut stdin = stdin.take().unwrap(); + let stdin = stdin.take().unwrap(); + let stdin = Arc::new(Mutex::new(stdin)); let stdout = stdout.take().unwrap(); let stdout = BufReader::new(stdout); let stderr = stderr.take().unwrap(); let stderr = BufReader::new(stderr); - let stderr = thread::Builder::new() - .spawn(move || { - for line in stderr.lines() { - let line = line.context("failed to read line from stderr")?; - eprintln!("{}", line); - // Try to get QEMU to exit on kernel panic; otherwise it might hang indefinitely. - if line.contains("end Kernel panic") { - stdin - .write_all(&[0x01, b'x']) - .context("failed to write to stdin")?; + fn terminate_if_contains_kernel_panic( + line: &str, + stdin: &Arc>, + ) -> anyhow::Result<()> { + if line.contains("end Kernel panic") { + println!("kernel panic detected; terminating QEMU"); + let mut stdin = stdin.lock().unwrap(); + stdin + .write_all(&[0x01, b'x']) + .context("failed to write to stdin")?; + println!("waiting for QEMU to terminate"); + } + Ok(()) + } + + let stderr = { + let stdin = stdin.clone(); + thread::Builder::new() + .spawn(move || { + for line in stderr.lines() { + let line = line.context("failed to read line from stderr")?; + eprintln!("{}", line); + // Try to get QEMU to exit on kernel panic; otherwise it might hang indefinitely. + terminate_if_contains_kernel_panic(&line, &stdin)?; } - } - anyhow::Ok(()) - }) - .unwrap(); + anyhow::Ok(()) + }) + .unwrap() + }; let mut outcome = None; for line in stdout.lines() { let line = line.context("failed to read line from stdout")?; println!("{}", line); + // Try to get QEMU to exit on kernel panic; otherwise it might hang indefinitely. + terminate_if_contains_kernel_panic(&line, &stdin)?; // The init program will print "init: success" or "init: failure" to indicate // the outcome of running the binaries it found in /bin. if let Some(line) = line.strip_prefix("init: ") {