Merge pull request #745 from aya-rs/even-more-aggro-kp-handling

xtask: watch for kernel panic in stdout too
reviewable/pr747/r1
Tamir Duberstein 1 year ago committed by GitHub
commit 68bf8818ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,7 +5,8 @@ use std::{
fs::{copy, create_dir_all, metadata, File}, fs::{copy, create_dir_all, metadata, File},
io::{BufRead as _, BufReader, ErrorKind, Write as _}, io::{BufRead as _, BufReader, ErrorKind, Write as _},
path::{Path, PathBuf}, path::{Path, PathBuf},
process::{Child, Command, Output, Stdio}, process::{Child, ChildStdin, Command, Output, Stdio},
sync::{Arc, Mutex},
thread, thread,
}; };
@ -392,7 +393,7 @@ pub fn run(opts: Options) -> Result<()> {
qemu.args(["-cpu", cpu]); qemu.args(["-cpu", cpu]);
} }
let console = OsString::from("ttyS0"); let console = OsString::from("ttyS0");
let kernel_args = std::iter::once(("console", &console)) let mut kernel_args = std::iter::once(("console", &console))
.chain(run_args.clone().map(|run_arg| ("init.arg", run_arg))) .chain(run_args.clone().map(|run_arg| ("init.arg", run_arg)))
.enumerate() .enumerate()
.fold(OsString::new(), |mut acc, (i, (k, v))| { .fold(OsString::new(), |mut acc, (i, (k, v))| {
@ -404,6 +405,12 @@ pub fn run(opts: Options) -> Result<()> {
acc.push(v); acc.push(v);
acc acc
}); });
// We sometimes see kernel panics containing:
//
// [ 0.064000] Kernel panic - not syncing: IO-APIC + timer doesn't work! Boot with apic=debug and send a report. Then try booting with the 'noapic' option.
//
// Heed the advice and boot with noapic. We don't know why this happens.
kernel_args.push(" noapic");
qemu.args(["-no-reboot", "-nographic", "-m", "512M", "-smp", "2"]) qemu.args(["-no-reboot", "-nographic", "-m", "512M", "-smp", "2"])
.arg("-append") .arg("-append")
.arg(kernel_args) .arg(kernel_args)
@ -462,32 +469,49 @@ pub fn run(opts: Options) -> Result<()> {
stderr, stderr,
.. ..
} = &mut qemu_child; } = &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 = stdout.take().unwrap();
let stdout = BufReader::new(stdout); let stdout = BufReader::new(stdout);
let stderr = stderr.take().unwrap(); let stderr = stderr.take().unwrap();
let stderr = BufReader::new(stderr); let stderr = BufReader::new(stderr);
let stderr = thread::Builder::new() fn terminate_if_contains_kernel_panic(
.spawn(move || { line: &str,
for line in stderr.lines() { stdin: &Arc<Mutex<ChildStdin>>,
let line = line.context("failed to read line from stderr")?; ) -> anyhow::Result<()> {
eprintln!("{}", line); if line.contains("end Kernel panic") {
// Try to get QEMU to exit on kernel panic; otherwise it might hang indefinitely. println!("kernel panic detected; terminating QEMU");
if line.contains("end Kernel panic") { let mut stdin = stdin.lock().unwrap();
stdin stdin
.write_all(&[0x01, b'x']) .write_all(&[0x01, b'x'])
.context("failed to write to stdin")?; .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(())
anyhow::Ok(()) })
}) .unwrap()
.unwrap(); };
let mut outcome = None; let mut outcome = None;
for line in stdout.lines() { for line in stdout.lines() {
let line = line.context("failed to read line from stdout")?; let line = line.context("failed to read line from stdout")?;
println!("{}", line); 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 init program will print "init: success" or "init: failure" to indicate
// the outcome of running the binaries it found in /bin. // the outcome of running the binaries it found in /bin.
if let Some(line) = line.strip_prefix("init: ") { if let Some(line) = line.strip_prefix("init: ") {

Loading…
Cancel
Save