krata: fix guest destruction

This commit is contained in:
Alex Zenla
2024-03-30 03:49:13 +00:00
parent d659b3aa55
commit da9e6cac14
12 changed files with 103 additions and 122 deletions

View File

@ -20,12 +20,12 @@ use crate::boot::BootSetup;
use crate::elfloader::ElfImageLoader;
use crate::error::{Error, Result};
use boot::BootState;
use log::{trace, warn};
use log::{debug, trace, warn};
use tokio::time::timeout;
use std::fs::read;
use std::path::PathBuf;
use std::str::FromStr;
use std::thread;
use std::time::Duration;
use uuid::Uuid;
use xencall::sys::{CreateDomain, XEN_DOMCTL_CDF_HAP, XEN_DOMCTL_CDF_HVM_GUEST};
@ -759,6 +759,7 @@ impl XenClient {
for backend in &backend_paths {
let state_path = format!("{}/state", backend);
let mut watch = self.store.create_watch(&state_path).await?;
let online_path = format!("{}/online", backend);
let tx = self.store.transaction().await?;
let state = tx.read_string(&state_path).await?.unwrap_or(String::new());
@ -769,22 +770,25 @@ impl XenClient {
if !state.is_empty() && u32::from_str(&state).unwrap_or(0) != 6 {
tx.write_string(&state_path, "5").await?;
}
self.store.bind_watch(&watch).await?;
tx.commit().await?;
let mut count: u32 = 0;
loop {
if count >= 100 {
warn!("unable to safely destroy backend: {}", backend);
if count >= 3 {
debug!("unable to safely destroy backend: {}", backend);
break;
}
let Some(state) = self.store.read_string(&state_path).await? else {
break;
};
let _ = timeout(Duration::from_secs(1), watch.receiver.recv()).await;
let state = self
.store
.read_string(&state_path)
.await?
.unwrap_or_else(|| "6".to_string());
let state = i64::from_str(&state).unwrap_or(-1);
if state == 6 {
break;
}
thread::sleep(Duration::from_millis(100));
count += 1;
}
}
@ -818,7 +822,7 @@ impl XenClient {
if tty.is_some() {
break;
}
thread::sleep(Duration::from_millis(200));
tokio::time::sleep(Duration::from_millis(200)).await;
}
let Some(tty) = tty else {
return Err(Error::TtyNotFound);

View File

@ -7,8 +7,8 @@ async fn main() -> Result<()> {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let path = args().nth(1).unwrap_or("/local/domain".to_string());
let client = XsdClient::open().await?;
let mut handle = client.create_watch().await?;
client.bind_watch(&handle, path).await?;
let mut handle = client.create_watch(path).await?;
client.bind_watch(&handle).await?;
let mut count = 0;
loop {
let Some(event) = handle.receiver.recv().await else {

View File

@ -65,7 +65,7 @@ pub struct XsdSocket {
next_watch_id: Arc<Mutex<u32>>,
processor_task: Arc<JoinHandle<()>>,
rx_task: Arc<JoinHandle<()>>,
unwatch_sender: Sender<u32>,
unwatch_sender: Sender<(u32, String)>,
}
impl XsdSocket {
@ -100,7 +100,7 @@ impl XsdSocket {
let (rx_sender, rx_receiver) = channel::<XsdMessage>(10);
let (tx_sender, tx_receiver) = channel::<XsdMessage>(10);
let (unwatch_sender, unwatch_receiver) = channel::<u32>(1000);
let (unwatch_sender, unwatch_receiver) = channel::<(u32, String)>(1000);
let read: File = handle.try_clone().await?;
let mut processor = XsdSocketProcessor {
@ -141,7 +141,7 @@ impl XsdSocket {
let req = {
let mut guard = self.next_request_id.lock().await;
let req = *guard;
*guard = req + 1;
*guard = req.wrapping_add(1);
req
};
let (sender, receiver) = oneshot_channel::<XsdMessage>();
@ -177,12 +177,12 @@ impl XsdSocket {
self.send_buf(tx, typ, &buf).await
}
pub async fn add_watch(&self) -> Result<(u32, Receiver<String>, Sender<u32>)> {
pub async fn add_watch(&self) -> Result<(u32, Receiver<String>, Sender<(u32, String)>)> {
let id = {
let mut guard = self.next_watch_id.lock().await;
let req = *guard;
*guard = req + 1;
req
let watch = *guard;
*guard = watch.wrapping_add(1);
watch
};
let (sender, receiver) = channel(10);
self.watches.lock().await.insert(id, WatchState { sender });
@ -197,7 +197,7 @@ struct XsdSocketProcessor {
next_request_id: Arc<Mutex<u32>>,
tx_receiver: Receiver<XsdMessage>,
rx_receiver: Receiver<XsdMessage>,
unwatch_receiver: Receiver<u32>,
unwatch_receiver: Receiver<(u32, String)>,
}
impl XsdSocketProcessor {
@ -326,16 +326,18 @@ impl XsdSocketProcessor {
},
x = self.unwatch_receiver.recv() => match x {
Some(id) => {
Some((id, path)) => {
let req = {
let mut guard = self.next_request_id.lock().await;
let req = *guard;
*guard = req + 1;
*guard = req.wrapping_add(1);
req
};
let mut payload = id.to_string().as_bytes().to_vec();
payload.push(0);
payload.extend_from_slice(path.to_string().as_bytes());
payload.push(0);
let header = XsdMessageHeader {
typ: XSD_UNWATCH,
req,

View File

@ -43,14 +43,15 @@ impl XsPermission {
}
pub struct XsdWatchHandle {
pub path: String,
pub id: u32,
unwatch_sender: Sender<u32>,
unwatch_sender: Sender<(u32, String)>,
pub receiver: Receiver<String>,
}
impl Drop for XsdWatchHandle {
fn drop(&mut self) {
let _ = self.unwatch_sender.try_send(self.id);
let _ = self.unwatch_sender.try_send((self.id, self.path.clone()));
}
}
@ -192,17 +193,18 @@ impl XsdClient {
response.parse_bool()
}
pub async fn create_watch(&self) -> Result<XsdWatchHandle> {
pub async fn create_watch<P: AsRef<str>>(&self, path: P) -> Result<XsdWatchHandle> {
let (id, receiver, unwatch_sender) = self.socket.add_watch().await?;
Ok(XsdWatchHandle {
path: path.as_ref().to_string(),
id,
receiver,
unwatch_sender,
})
}
pub async fn bind_watch<P: AsRef<str>>(&self, handle: &XsdWatchHandle, path: P) -> Result<()> {
self.bind_watch_id(handle.id, path).await
pub async fn bind_watch(&self, handle: &XsdWatchHandle) -> Result<()> {
self.bind_watch_id(handle.id, &handle.path).await
}
pub async fn bind_watch_id<P: AsRef<str>>(&self, id: u32, path: P) -> Result<()> {