Procházet zdrojové kódy

xtask: watch for kernel panic in stdout too

Seems unclear whether kernel panics go to stdout or stderr, so do them
both.
Tamir Duberstein před 1 rokem
rodič
revize
de65ba0067
1 změnil soubory, kde provedl 34 přidání a 16 odebrání
  1. 34 16
      xtask/src/run.rs

+ 34 - 16
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<Mutex<ChildStdin>>,
+                ) -> 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: ") {