Merge "microdroid_manager: wait for failure reason to transmit" into main am: 3f48fcfc16 am: e633c5e456
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Virtualization/+/3353265
Change-Id: I1ad162dfbd39eddf600113759a106aa23649f85c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index 94379a9..b0944fc 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -475,10 +475,23 @@
fn monitor_vm_exit(
&self,
child: Arc<SharedChild>,
- mut failure_pipe_read: File,
+ failure_pipe_read: File,
vfio_devices: Vec<VfioDevice>,
tap: Option<File>,
) {
+ let failure_reason_thread = std::thread::spawn(move || {
+ // Read the pipe to see if any failure reason is written
+ let mut failure_reason = String::new();
+ // Arbitrary max size in case of misbehaving guest.
+ const MAX_SIZE: u64 = 50_000;
+ match failure_pipe_read.take(MAX_SIZE).read_to_string(&mut failure_reason) {
+ Err(e) => error!("Error reading VM failure reason from pipe: {}", e),
+ Ok(len) if len > 0 => error!("VM returned failure reason '{}'", &failure_reason),
+ _ => (),
+ };
+ failure_reason
+ });
+
let result = child.wait();
match &result {
Err(e) => error!("Error waiting for crosvm({}) instance to die: {}", child.id(), e),
@@ -492,20 +505,14 @@
}
}
+ let failure_reason = failure_reason_thread.join().expect("failure_reason_thread panic'd");
+
let mut vm_state = self.vm_state.lock().unwrap();
*vm_state = VmState::Dead;
// Ensure that the mutex is released before calling the callbacks.
drop(vm_state);
info!("{} exited", &self);
- // Read the pipe to see if any failure reason is written
- let mut failure_reason = String::new();
- match failure_pipe_read.read_to_string(&mut failure_reason) {
- Err(e) => error!("Error reading VM failure reason from pipe: {}", e),
- Ok(len) if len > 0 => info!("VM returned failure reason '{}'", &failure_reason),
- _ => (),
- };
-
// In case of hangup, the pipe doesn't give us any information because the hangup can't be
// detected on the VM side (otherwise, it isn't a hangup), but in the
// monitor_payload_hangup function below which updates the payload state to Hangup.
diff --git a/guest/microdroid_manager/src/main.rs b/guest/microdroid_manager/src/main.rs
index 6bf3ed9..4b261c4 100644
--- a/guest/microdroid_manager/src/main.rs
+++ b/guest/microdroid_manager/src/main.rs
@@ -140,10 +140,10 @@
Owned(format!("MICRODROID_UNKNOWN_RUNTIME_ERROR|{:?}", err))
};
- for chunk in death_reason.as_bytes().chunks(16) {
- // TODO(b/220071963): Sometimes, sending more than 16 bytes at once makes MM hang.
- OpenOptions::new().read(false).write(true).open(FAILURE_SERIAL_DEVICE)?.write_all(chunk)?;
- }
+ let mut serial_file = OpenOptions::new().read(false).write(true).open(FAILURE_SERIAL_DEVICE)?;
+ serial_file.write_all(death_reason.as_bytes()).context("serial device write_all failed")?;
+ // Block until the serial port trasmits all the data to the host.
+ nix::sys::termios::tcdrain(&serial_file).context("tcdrain failed")?;
Ok(())
}