Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions vm-migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
//

use std::error::Error;
use std::iter;

use anyhow::anyhow;
pub use context::{
CompletedMigrationContext, DowntimeContext, MemoryMigrationContext, MigrationContextError,
Expand All @@ -20,6 +23,21 @@ pub mod progress;
pub mod protocol;
pub mod tls;

/// Mimics the error chain printing of CH for migration-related errors, where we
/// do not exit the VMM (which would print the error chain).
pub fn nested_error_to_flat_chain_as_string(top_error: &dyn Error) -> 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::<Vec<_>>()
.join(" => ")
}

#[derive(Error, Debug)]
pub enum UffdError {
#[error("Snapshot ranges are not page-aligned")]
Expand Down
4 changes: 3 additions & 1 deletion vm-migration/src/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use std::fmt::Display;
use std::num::NonZeroU32;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use crate::nested_error_to_flat_chain_as_string;

#[derive(
Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
Expand Down Expand Up @@ -329,7 +331,7 @@ impl MigrationProgress {
self.timestamp_snapshot_ms = current_unix_timestamp_ms();
self.timestamp_snapshot_relative_ms = self.timestamp_snapshot_ms - self.timestamp_begin_ms;
self.state = MigrationState::Failed {
error_msg: format!("{error}",),
error_msg: nested_error_to_flat_chain_as_string(error),
error_msg_debug: format!("{error:?}",),
};
}
Expand Down
38 changes: 5 additions & 33 deletions vmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use vm_migration::progress::{
use vm_migration::protocol::*;
use vm_migration::{
MemoryMigrationContext, Migratable, MigratableError, OngoingMigrationContext, Pausable,
Snapshot, Snapshottable, Transportable,
Snapshot, Snapshottable, Transportable, nested_error_to_flat_chain_as_string,
};
use vmm_sys_util::eventfd::EventFd;
use vmm_sys_util::signal::unblock_signal;
Expand Down Expand Up @@ -2213,37 +2213,6 @@ impl Vmm {
self.vm.vm_mut().unwrap().restore()
}

/// Prints the error chain to `error!()` level, akin to user-facing errors when Cloud Hypervisor
/// or ch-remote fail.
// TODO: For upstreaming, we should unify this with the code-paths used by ch-remote and
// Cloud Hypervisor on failure.
fn log_print_error_chain<'a>(top_error: &'a (dyn std::error::Error + 'static)) {
// Print chain of errors
if top_error.source().is_none() {
error!("Migration failed with the following error:");
error!(" {top_error}");
} else {
// In cli_print_error_chain(), we also print the
// <top_err as Debug>::fmt() as oneliner so that we can see all
// properties. As we use anyhow errors in the migration path,
// Debug::fmt() is not helpful for us as it doesn't print the
// underlying properties (like the default Debug::fmt() impl would
// do). Instead, it would print a trace itself, which is not what
// we want to do here.

error!("Migration failed with the following chain of errors:");
std::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()
})
.enumerate()
.for_each(|(level, error)| {
error!(" {level}: {error}");
});
}
}

/// Checks the migration result.
///
/// This should be called when the migration thread indicated a state
Expand Down Expand Up @@ -2345,7 +2314,10 @@ impl Vmm {
}
}
Err(e) => {
Self::log_print_error_chain(&e);
error!(
"Migration failed: {}",
nested_error_to_flat_chain_as_string(&e)
);
try_resume_vm(vm);

// Update migration progress snapshot
Expand Down
Loading