Skip to content
Draft
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
346 changes: 205 additions & 141 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ path = "src/lib.rs"
name = "lunatic"
path = "src/main.rs"

[[bin]]
name = "cargo-lunatic"
path = "src/cargo_lunatic.rs"

[features]
default = ["metrics"]
metrics = [
"lunatic-process-api/metrics",
"lunatic-process/metrics",
"lunatic-registry-api/metrics",
"lunatic-timer-api/metrics",
"dep:lunatic-metrics-api",
]
prometheus = ["dep:metrics-exporter-prometheus", "metrics"]

Expand All @@ -41,6 +46,7 @@ lunatic-registry-api = { workspace = true }
lunatic-stdout-capture = { workspace = true }
lunatic-timer-api = { workspace = true }
lunatic-version-api = { workspace = true }
lunatic-metrics-api = { workspace = true, optional = true }
lunatic-wasi-api = { workspace = true }

anyhow = { workspace = true }
Expand Down Expand Up @@ -96,6 +102,7 @@ lunatic-registry-api = { path = "crates/lunatic-registry-api", version = "0.12"
lunatic-stdout-capture = { path = "crates/lunatic-stdout-capture", version = "0.12" }
lunatic-timer-api = { path = "crates/lunatic-timer-api", version = "0.12" }
lunatic-version-api = { path = "crates/lunatic-version-api", version = "0.12" }
lunatic-metrics-api = { path = "crates/lunatic-metrics-api", version = "0.12" }
lunatic-wasi-api = { path = "crates/lunatic-wasi-api", version = "0.12" }

anyhow = "1.0"
Expand All @@ -105,5 +112,8 @@ metrics = "0.20.1"
rustls-pemfile = "1.0"
serde = "1.0"
tokio = "1.20"
wasmtime = "2.0"
wasmtime-wasi = "2.0"
wasmtime = "3.0"
wasmtime-runtime = "3.0.1"
wasmtime-wasi = "3.0.1"
wasi-common = "3.0.1"
wiggle = "3.0.1"
23 changes: 12 additions & 11 deletions crates/lunatic-common-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use anyhow::Result;
use anyhow::{anyhow, Result};
use std::fmt::Display;
use wasmtime::{Caller, Memory, Trap};
use wasmtime::{Caller, Memory};

// Get exported memory
pub fn get_memory<T>(caller: &mut Caller<T>) -> std::result::Result<Memory, Trap> {
pub fn get_memory<T>(caller: &mut Caller<T>) -> Result<Memory> {
caller
.get_export("memory")
.or_trap("No export `memory` found")?
Expand All @@ -12,30 +12,31 @@ pub fn get_memory<T>(caller: &mut Caller<T>) -> std::result::Result<Memory, Trap
}

pub trait IntoTrap<T> {
fn or_trap<S: Display>(self, info: S) -> Result<T, Trap>;
fn or_trap<S: Display>(self, info: S) -> Result<T>;
}

impl<T, E: Display> IntoTrap<T> for Result<T, E> {
fn or_trap<S: Display>(self, info: S) -> Result<T, Trap> {
fn or_trap<S: Display>(self, info: S) -> Result<T> {
match self {
Ok(result) => Ok(result),
Err(error) => Err(Trap::new(format!(
Err(error) => Err(anyhow!(
"Trap raised during host call: {} ({}).",
error, info
))),
error,
info
)),
}
}
}

impl<T> IntoTrap<T> for Option<T> {
fn or_trap<S: Display>(self, info: S) -> Result<T, Trap> {
fn or_trap<S: Display>(self, info: S) -> Result<T> {
match self {
Some(result) => Ok(result),
None => Err(Trap::new(format!(
None => Err(anyhow!(
"Trap raised during host call: Expected `Some({})` got `None` ({}).",
std::any::type_name::<T>(),
info
))),
)),
}
}
}
43 changes: 22 additions & 21 deletions crates/lunatic-distributed-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use lunatic_process::{
};
use lunatic_process_api::ProcessCtx;
use tokio::time::timeout;
use wasmtime::{Caller, Linker, ResourceLimiter, Trap};
use wasmtime::{Caller, Linker, ResourceLimiter};

// Register the lunatic distributed APIs to the linker
pub fn register<T, E>(linker: &mut Linker<T>) -> Result<()>
Expand Down Expand Up @@ -63,7 +63,7 @@ where
//
// Traps:
// * If any memory outside the guest heap space is referenced.
fn get_nodes<T, E>(mut caller: Caller<T>, nodes_ptr: u32, nodes_len: u32) -> Result<u32, Trap>
fn get_nodes<T, E>(mut caller: Caller<T>, nodes_ptr: u32, nodes_len: u32) -> Result<u32>
where
T: DistributedCtx<E>,
E: Environment,
Expand All @@ -78,8 +78,7 @@ where
memory
.data_mut(&mut caller)
.get_mut(
nodes_ptr as usize
..(nodes_ptr as usize + std::mem::size_of::<u64>() * copy_nodes_len as usize),
nodes_ptr as usize..(nodes_ptr as usize + std::mem::size_of::<u64>() * copy_nodes_len),
)
.or_trap("lunatic::distributed::get_nodes::memory")?
.copy_from_slice(unsafe { node_ids[..copy_nodes_len].align_to::<u8>().1 });
Expand All @@ -101,7 +100,7 @@ fn exec_lookup_nodes<T, E>(
query_id_ptr: u32,
nodes_len_ptr: u32,
error_ptr: u32,
) -> Box<dyn Future<Output = Result<u32, Trap>> + Send + '_>
) -> Box<dyn Future<Output = Result<u32>> + Send + '_>
where
T: DistributedCtx<E> + ErrorCtx + Send + 'static,
E: Environment + 'static,
Expand Down Expand Up @@ -151,7 +150,7 @@ fn copy_lookup_nodes_results<T, E>(
nodes_ptr: u32,
nodes_len: u32,
error_ptr: u32,
) -> Result<i32, Trap>
) -> Result<i32>
where
T: DistributedCtx<E> + ErrorCtx,
E: Environment,
Expand All @@ -169,7 +168,7 @@ where
.data_mut(&mut caller)
.get_mut(
nodes_ptr as usize
..(nodes_ptr as usize + std::mem::size_of::<u64>() * copy_nodes_len as usize),
..(nodes_ptr as usize + std::mem::size_of::<u64>() * copy_nodes_len),
)
.or_trap("lunatic::distributed::copy_lookup_nodes_results::memory")?
.copy_from_slice(unsafe { nodes[..copy_nodes_len].align_to::<u8>().1 });
Expand Down Expand Up @@ -220,15 +219,17 @@ fn spawn<T, E>(
params_ptr: u32,
params_len: u32,
id_ptr: u32,
) -> Box<dyn Future<Output = Result<u32, Trap>> + Send + '_>
) -> Box<dyn Future<Output = Result<u32>> + Send + '_>
where
T: DistributedCtx<E> + ResourceLimiter + Send + ErrorCtx + 'static,
E: Environment,
for<'a> &'a T: Send,
{
Box::new(async move {
if !caller.data().can_spawn() {
return Err(anyhow!("Process doesn't have permissions to spawn sub-processes").into());
return Err(anyhow!(
"Process doesn't have permissions to spawn sub-processes"
));
}
let memory = get_memory(&mut caller)?;
let func_str = memory
Expand Down Expand Up @@ -293,11 +294,11 @@ where
Ok(process_id) => (process_id, 0),
Err(error) => {
let (code, message): (u32, String) = match error {
ClientError::Unexpected(cause) => Err(Trap::new(cause)),
ClientError::Unexpected(cause) => Err(anyhow!(cause)),
ClientError::NodeNotFound => Ok((1, "Node does not exist.".to_string())),
ClientError::ModuleNotFound => Ok((2, "Module does not exist.".to_string())),
ClientError::Connection(cause) => Ok((9027, cause)),
_ => Err(Trap::new("unreachable")),
_ => Err(anyhow!("unreachable")),
}?;
(
caller
Expand Down Expand Up @@ -338,7 +339,7 @@ fn send<T, E>(
mut caller: Caller<T>,
node_id: u64,
process_id: u64,
) -> Box<dyn Future<Output = Result<u32, Trap>> + Send + '_>
) -> Box<dyn Future<Output = Result<u32>> + Send + '_>
where
T: DistributedCtx<E> + ProcessCtx<T> + Send + ErrorCtx + 'static,
E: Environment,
Expand All @@ -359,7 +360,7 @@ where
}) = message
{
if !resources.is_empty() {
return Err(Trap::new("Cannot send resources to remote nodes."));
return Err(anyhow!("Cannot send resources to remote nodes."));
}

let state = caller.data();
Expand All @@ -371,15 +372,15 @@ where
{
Ok(_) => Ok(0),
Err(error) => match error {
ClientError::Unexpected(cause) => Err(Trap::new(cause)),
ClientError::Unexpected(cause) => Err(anyhow!(cause)),
ClientError::ProcessNotFound => Ok(1),
ClientError::NodeNotFound => Ok(2),
ClientError::Connection(_) => Ok(9027),
_ => Err(Trap::new("unreachable")),
_ => Err(anyhow!("unreachable")),
},
}
} else {
Err(Trap::new("Only Message::Data can be sent across nodes."))
Err(anyhow!("Only Message::Data can be sent across nodes."))
}
})
}
Expand Down Expand Up @@ -410,7 +411,7 @@ fn send_receive_skip_search<T, E>(
node_id: u64,
process_id: u64,
timeout_duration: u64,
) -> Box<dyn Future<Output = Result<u32, Trap>> + Send + '_>
) -> Box<dyn Future<Output = Result<u32>> + Send + '_>
where
T: DistributedCtx<E> + ProcessCtx<T> + Send + 'static,
E: Environment,
Expand Down Expand Up @@ -439,7 +440,7 @@ where
}) = message
{
if !resources.is_empty() {
return Err(Trap::new("Cannot send resources to remote nodes."));
return Err(anyhow!("Cannot send resources to remote nodes."));
}

let state = caller.data();
Expand All @@ -453,8 +454,8 @@ where
Err(error) => match error {
ClientError::ProcessNotFound => Ok(1),
ClientError::NodeNotFound => Ok(2),
ClientError::Unexpected(cause) => Err(Trap::new(cause)),
_ => Err(Trap::new("unreachable")),
ClientError::Unexpected(cause) => Err(anyhow!(cause)),
_ => Err(anyhow!("unreachable")),
},
}?;

Expand All @@ -476,7 +477,7 @@ where
Ok(9027)
}
} else {
Err(Trap::new("Only Message::Data can be sent across nodes."))
Err(anyhow!("Only Message::Data can be sent across nodes."))
}
})
}
Expand Down
11 changes: 3 additions & 8 deletions crates/lunatic-error-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use anyhow::Result;
use hash_map_id::HashMapId;
use lunatic_common_api::{get_memory, IntoTrap};
use wasmtime::Trap;
use wasmtime::{Caller, Linker};

pub type ErrorResource = HashMapId<anyhow::Error>;
Expand All @@ -23,7 +22,7 @@ pub fn register<T: ErrorCtx + 'static>(linker: &mut Linker<T>) -> Result<()> {
//
// Traps:
// * If the error ID doesn't exist.
fn string_size<T: ErrorCtx>(caller: Caller<T>, error_id: u64) -> Result<u32, Trap> {
fn string_size<T: ErrorCtx>(caller: Caller<T>, error_id: u64) -> Result<u32> {
let error = caller
.data()
.error_resources()
Expand All @@ -38,11 +37,7 @@ fn string_size<T: ErrorCtx>(caller: Caller<T>, error_id: u64) -> Result<u32, Tra
// Traps:
// * If the error ID doesn't exist.
// * If any memory outside the guest heap space is referenced.
fn to_string<T: ErrorCtx>(
mut caller: Caller<T>,
error_id: u64,
error_str_ptr: u32,
) -> Result<(), Trap> {
fn to_string<T: ErrorCtx>(mut caller: Caller<T>, error_id: u64, error_str_ptr: u32) -> Result<()> {
let error = caller
.data()
.error_resources()
Expand All @@ -60,7 +55,7 @@ fn to_string<T: ErrorCtx>(
//
// Traps:
// * If the error ID doesn't exist.
fn drop<T: ErrorCtx>(mut caller: Caller<T>, error_id: u64) -> Result<(), Trap> {
fn drop<T: ErrorCtx>(mut caller: Caller<T>, error_id: u64) -> Result<()> {
caller
.data_mut()
.error_resources_mut()
Expand Down
Loading