mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: streamline printing of error chains
In [0] we agreed on the current format. - Use `: ` over ` => ` - Streamline usages in a helper Context https://github.com/cloud-hypervisor/cloud-hypervisor/issues/8510 [0] https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7066 On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit is contained in:
committed by
Rob Bradford
parent
53a00c0514
commit
da80fde887
@@ -12,7 +12,7 @@ use std::panic::AssertUnwindSafe;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::{fs, iter, panic, result, thread};
|
||||
use std::{fs, panic, result, thread};
|
||||
|
||||
use block::fcntl::{LockError, LockGranularity, LockType, try_acquire_lock};
|
||||
use log::{error, info};
|
||||
@@ -35,6 +35,7 @@ use crate::api::{
|
||||
};
|
||||
use crate::landlock::Landlock;
|
||||
use crate::seccomp_filters::{Thread, get_seccomp_filter};
|
||||
use crate::util::{error_chain_messages, flatten_error_chain_to_string};
|
||||
use crate::vm::Error as VmError;
|
||||
use crate::{Error as VmmError, Result};
|
||||
|
||||
@@ -102,20 +103,13 @@ const HTTP_ROOT: &str = "/api/v1";
|
||||
pub fn error_response(error: HttpError) -> Response {
|
||||
let mut response = Response::new(Version::Http11, error.status_code());
|
||||
|
||||
let error: &dyn Error = &error;
|
||||
// Write the Display::display() output all errors (from top to root).
|
||||
let error_messages = iter::successors(Some(error), |sub_error| {
|
||||
// Dereference necessary to mitigate rustc compiler bug.
|
||||
// See <https://github.com/rust-lang/rust/issues/141673>
|
||||
(*sub_error).source()
|
||||
})
|
||||
.map(|error| format!("{error}"))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
info!("HTTP API error response: {}", error_messages.join(": "));
|
||||
info!(
|
||||
"HTTP API error response: {}",
|
||||
flatten_error_chain_to_string(&error)
|
||||
);
|
||||
|
||||
// TODO: Move `api` module from `vmm` to dedicated crate and use a common type definition
|
||||
let json = serde_json::to_string(&error_messages).unwrap();
|
||||
let json = serde_json::to_string(&error_chain_messages(&error)).unwrap();
|
||||
|
||||
let body = Body::new(json);
|
||||
response.set_body(body);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error as StdError;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write, stdout};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
@@ -16,7 +15,7 @@ use std::sync::mpsc;
|
||||
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender, channel};
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{any, io, iter, mem, panic, path, process, result, thread};
|
||||
use std::{any, io, mem, panic, path, process, result, thread};
|
||||
|
||||
use anyhow::{Context, anyhow};
|
||||
#[cfg(feature = "dbus_api")]
|
||||
@@ -2033,22 +2032,10 @@ impl Vmm {
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// Mimic the error chain that CH prints on error in the log.
|
||||
// Required to get useful error messages in the log.
|
||||
let top_error: &dyn StdError = &e;
|
||||
let error_chain_str = {
|
||||
iter::successors(Some(top_error), |sub_error| {
|
||||
// Dereference necessary to mitigate rustc compiler bug.
|
||||
// See <https://github.com/rust-lang/rust/issues/141673>
|
||||
(*sub_error).source()
|
||||
})
|
||||
// Important to use the plain Display impl to not interfere
|
||||
// with anyhow's "smart" printing
|
||||
.map(|e| format!("{e}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" => ")
|
||||
};
|
||||
error!("Migration failed: {error_chain_str}");
|
||||
error!(
|
||||
"Migration failed: {}",
|
||||
util::flatten_error_chain_to_string(&e)
|
||||
);
|
||||
try_resume_vm_after_failed_migration(vm);
|
||||
}
|
||||
}
|
||||
@@ -3240,6 +3227,36 @@ const CPU_MANAGER_SNAPSHOT_ID: &str = "cpu-manager";
|
||||
const MEMORY_MANAGER_SNAPSHOT_ID: &str = "memory-manager";
|
||||
const DEVICE_MANAGER_SNAPSHOT_ID: &str = "device-manager";
|
||||
|
||||
mod util {
|
||||
use std::error::Error as StdError;
|
||||
use std::iter;
|
||||
|
||||
/// Creates in iterator over the [`Display`]-formatted representations of
|
||||
/// the chain of errors of a [`StdError`].
|
||||
///
|
||||
/// The first index is the top error, the last index is the root cause.
|
||||
///
|
||||
/// This mimics the error chain that we print on exit in CH or ch-remote for
|
||||
/// situations where we do not exit the program.
|
||||
pub fn error_chain_messages(top_error: &dyn StdError) -> Vec<String> {
|
||||
iter::successors(Some(top_error), |sub_error| {
|
||||
// Dereference necessary to mitigate rustc compiler bug.
|
||||
// See <https://github.com/rust-lang/rust/issues/141673>
|
||||
(*sub_error).source()
|
||||
})
|
||||
// Important to use the plain Display impl to not interfere
|
||||
// with anyhow's "smart" printing
|
||||
.map(|e| format!("{e}"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Flattens the chain of errors of a [`StdError`] into a single printable
|
||||
/// line.
|
||||
pub fn flatten_error_chain_to_string(top_error: &dyn StdError) -> String {
|
||||
// Separator discussed here: https://github.com/cloud-hypervisor/cloud-hypervisor/issues/8510
|
||||
error_chain_messages(top_error).join(": ")
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
Reference in New Issue
Block a user