mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 21:21:32 +00:00
controller: implement automatic exit when process has exited
This commit is contained in:
@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use log::warn;
|
use log::debug;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use termion::raw::IntoRawMode;
|
use termion::raw::IntoRawMode;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
@ -34,7 +34,7 @@ impl XenConsole {
|
|||||||
let stdout = unsafe { File::from_raw_fd(terminal.as_raw_fd()) };
|
let stdout = unsafe { File::from_raw_fd(terminal.as_raw_fd()) };
|
||||||
let reader_task = tokio::task::spawn(async move {
|
let reader_task = tokio::task::spawn(async move {
|
||||||
if let Err(error) = XenConsole::copy_stdout(stdout, self.xen_read_handle).await {
|
if let Err(error) = XenConsole::copy_stdout(stdout, self.xen_read_handle).await {
|
||||||
warn!("failed to copy console output: {}", error);
|
debug!("failed to copy console output: {}", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let writer_task = tokio::task::spawn(async move {
|
let writer_task = tokio::task::spawn(async move {
|
||||||
@ -44,7 +44,7 @@ impl XenConsole {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
warn!("failed to intercept stdin: {}", error);
|
debug!("failed to intercept stdin: {}", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use std::{process::exit, time::Duration};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use log::warn;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
use xenstore::client::XsdInterface;
|
||||||
|
|
||||||
|
use super::destroy::ControllerDestroy;
|
||||||
use crate::console::XenConsole;
|
use crate::console::XenConsole;
|
||||||
|
|
||||||
use super::ControllerContext;
|
use super::ControllerContext;
|
||||||
@ -22,7 +28,24 @@ impl ControllerConsole<'_> {
|
|||||||
let domid = info.domid;
|
let domid = info.domid;
|
||||||
let tty = self.context.xen.get_console_path(domid).await?;
|
let tty = self.context.xen.get_console_path(domid).await?;
|
||||||
let console = XenConsole::new(&tty).await?;
|
let console = XenConsole::new(&tty).await?;
|
||||||
console.attach().await?;
|
|
||||||
Ok(())
|
let dom_path = self.context.xen.store.get_domain_path(domid).await?;
|
||||||
|
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
if let Err(error) = console.attach().await {
|
||||||
|
warn!("failed to attach to console: {}", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let exit_code_path = format!("{}/krata/guest/exit-code", dom_path);
|
||||||
|
loop {
|
||||||
|
let Some(code) = self.context.xen.store.read_string(&exit_code_path).await? else {
|
||||||
|
sleep(Duration::from_secs(1)).await;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let mut destroy = ControllerDestroy::new(self.context);
|
||||||
|
destroy.perform(&domid.to_string()).await?;
|
||||||
|
exit(code.parse::<i32>()?);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::sys::{XsdMessageHeader, XSD_ERROR};
|
use crate::sys::{XsdMessageHeader, XSD_ERROR};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fs::{self, metadata, File};
|
use std::fs::{metadata, File};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::os::unix::fs::FileTypeExt;
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|
||||||
use tokio::net::UnixStream;
|
|
||||||
|
|
||||||
const XEN_BUS_PATHS: &[&str] = &["/dev/xen/xenbus", "/var/run/xenstored/socket"];
|
const XEN_BUS_PATHS: &[&str] = &["/dev/xen/xenbus"];
|
||||||
|
|
||||||
fn find_bus_path() -> Option<String> {
|
fn find_bus_path() -> Option<String> {
|
||||||
for path in XEN_BUS_PATHS {
|
for path in XEN_BUS_PATHS {
|
||||||
@ -20,37 +17,16 @@ fn find_bus_path() -> Option<String> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
trait XsdTransport {
|
|
||||||
async fn xsd_write_all(&mut self, buf: &[u8]) -> Result<()>;
|
|
||||||
async fn xsd_read_exact(&mut self, buf: &mut [u8]) -> Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl XsdTransport for UnixStream {
|
|
||||||
async fn xsd_write_all(&mut self, buf: &[u8]) -> Result<()> {
|
|
||||||
Ok(self.write_all(buf).await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn xsd_read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
|
|
||||||
self.read_exact(buf).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct XsdFileTransport {
|
pub struct XsdFileTransport {
|
||||||
handle: File,
|
handle: File,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XsdFileTransport {
|
impl XsdFileTransport {
|
||||||
pub fn new(path: &str) -> Result<XsdFileTransport> {
|
fn new(path: &str) -> Result<XsdFileTransport> {
|
||||||
let handle = File::options().read(true).write(true).open(path)?;
|
let handle = File::options().read(true).write(true).open(path)?;
|
||||||
Ok(XsdFileTransport { handle })
|
Ok(XsdFileTransport { handle })
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
|
||||||
impl XsdTransport for XsdFileTransport {
|
|
||||||
async fn xsd_read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
|
async fn xsd_read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
|
||||||
Ok(self.handle.read_exact(buf)?)
|
Ok(self.handle.read_exact(buf)?)
|
||||||
}
|
}
|
||||||
@ -63,7 +39,7 @@ impl XsdTransport for XsdFileTransport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct XsdSocket {
|
pub struct XsdSocket {
|
||||||
handle: Box<dyn XsdTransport>,
|
handle: XsdFileTransport,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -103,19 +79,8 @@ impl XsdSocket {
|
|||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => return Err(Error::BusNotFound),
|
None => return Err(Error::BusNotFound),
|
||||||
};
|
};
|
||||||
|
|
||||||
let metadata = fs::metadata(&path)?;
|
|
||||||
let file_type = metadata.file_type();
|
|
||||||
if file_type.is_socket() {
|
|
||||||
let stream = UnixStream::connect(&path).await?;
|
|
||||||
return Ok(XsdSocket {
|
|
||||||
handle: Box::new(stream),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let transport = XsdFileTransport::new(&path)?;
|
let transport = XsdFileTransport::new(&path)?;
|
||||||
Ok(XsdSocket {
|
Ok(XsdSocket { handle: transport })
|
||||||
handle: Box::new(transport),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self, tx: u32, typ: u32, buf: &[u8]) -> Result<XsdResponse> {
|
pub async fn send(&mut self, tx: u32, typ: u32, buf: &[u8]) -> Result<XsdResponse> {
|
||||||
|
Reference in New Issue
Block a user