Skip to content
Open
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
1,427 changes: 738 additions & 689 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ repository = "https://github.com/hyperlight-dev/hyperlight-wasm"
readme = "README.md"

[workspace.dependencies]
hyperlight-common = { version = "0.16.0", default-features = false }
hyperlight-component-macro = { version = "0.16.0" }
hyperlight-component-util = { version = "0.16.0" }
hyperlight-guest = { version = "0.16.0" }
hyperlight-guest-bin = { version = "0.16.0"}
hyperlight-host = { version = "0.16.0", default-features = false }
hyperlight-common = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "cfa020441d880d599cc516a050e6cf10236ca5c4", default-features = false }
hyperlight-component-macro = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "cfa020441d880d599cc516a050e6cf10236ca5c4" }
hyperlight-component-util = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "cfa020441d880d599cc516a050e6cf10236ca5c4" }
hyperlight-guest = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "cfa020441d880d599cc516a050e6cf10236ca5c4" }
hyperlight-guest-bin = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "cfa020441d880d599cc516a050e6cf10236ca5c4" }
hyperlight-host = { git = "https://github.com/hyperlight-dev/hyperlight", rev = "cfa020441d880d599cc516a050e6cf10236ca5c4", default-features = false }
hyperlight-wasm-macro = { version = "0.14.0", path = "src/hyperlight_wasm_macro" }
hyperlight-wasm-runtime = { version = "0.14.0", path = "src/hyperlight_wasm_runtime" }
10 changes: 6 additions & 4 deletions src/hyperlight_wasm/benches/benchmarks_components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Default for State {
}
}

impl bindings::example::runcomponent::Host for State {
impl bindings::example::runcomponent::Host<hyperlight_common::component::Negative> for State {
fn r#get_time_since_boot_microsecond(&mut self) -> i64 {
let res = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
Expand All @@ -35,7 +35,9 @@ impl bindings::example::runcomponent::Host for State {
}
}

impl bindings::example::runcomponent::RuncomponentImports for State {
impl bindings::example::runcomponent::RuncomponentImports<hyperlight_common::component::Negative>
for State
{
type Host = State;

fn r#host(&mut self) -> impl ::core::borrow::BorrowMut<Self::Host> {
Expand All @@ -52,7 +54,7 @@ fn wasm_component_guest_call_benchmark(c: &mut Criterion) {
let instance = bindings::example::runcomponent::RuncomponentExports::guest(&mut wrapped);

b.iter(|| {
instance.echo("Hello World!".to_string());
instance.echo("Hello World!".to_string()).unwrap();
});
};

Expand Down Expand Up @@ -86,7 +88,7 @@ fn get_loaded_wasm_sandbox() -> (
) {
let state = State::new();
let mut sandbox = SandboxBuilder::new().build().unwrap();
let rt = bindings::register_host_functions(&mut sandbox, state);
let rt = bindings::register_host_functions(&mut sandbox, state).unwrap();

let sb = sandbox.load_runtime().unwrap();

Expand Down
12 changes: 7 additions & 5 deletions src/hyperlight_wasm/examples/c-component/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl Default for State {
}
}

impl bindings::example::runcomponent::Host for State {
impl bindings::example::runcomponent::Host<hyperlight_common::component::Negative> for State {
fn r#get_time_since_boot_microsecond(&mut self) -> i64 {
let res = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
Expand All @@ -33,7 +33,9 @@ impl bindings::example::runcomponent::Host for State {
}
}

impl bindings::example::runcomponent::RuncomponentImports for State {
impl bindings::example::runcomponent::RuncomponentImports<hyperlight_common::component::Negative>
for State
{
type Host = State;

fn r#host(&mut self) -> impl ::core::borrow::BorrowMut<Self::Host> {
Expand All @@ -47,7 +49,7 @@ fn main() {
//.with_debugging_enabled(8080)
.build()
.unwrap();
let rt = bindings::register_host_functions(&mut sandbox, state);
let rt = bindings::register_host_functions(&mut sandbox, state).unwrap();

let sb = sandbox.load_runtime().unwrap();

Expand All @@ -56,10 +58,10 @@ fn main() {

let mut wrapped = bindings::RuncomponentSandbox { sb, rt };
let instance = bindings::example::runcomponent::RuncomponentExports::guest(&mut wrapped);
let echo = instance.echo("Hello World!".to_string());
let echo = instance.echo("Hello World!".to_string()).unwrap();
println!("{}", echo);

let result = instance.round_to_nearest_int(1.331, 24.0);
let result = instance.round_to_nearest_int(1.331, 24.0).unwrap();
println!("rounded result {}", result);
assert_eq!(result, 32);
}
16 changes: 9 additions & 7 deletions src/hyperlight_wasm/examples/component_example/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Default for State {
}
}

impl bindings::component_sample::example::Host for State {
impl bindings::component_sample::example::Host<hyperlight_common::component::Negative> for State {
fn r#print(&mut self, message: alloc::string::String) {
assert_eq!("42", message);
println!("Logged from component: {message}");
Expand All @@ -37,7 +37,9 @@ impl bindings::component_sample::example::Host for State {
}

#[allow(refining_impl_trait)]
impl bindings::component_sample::example::ExampleImports for State {
impl bindings::component_sample::example::ExampleImports<hyperlight_common::component::Negative>
for State
{
type Host = State;

fn r#host(&mut self) -> &mut Self {
Expand All @@ -53,7 +55,7 @@ fn main() {
.with_guest_scratch_size(100 * 1024 * 1024)
.build()
.unwrap();
let rt = bindings::register_host_functions(&mut sb, state);
let rt = bindings::register_host_functions(&mut sb, state).unwrap();

let sb = sb.load_runtime().unwrap();

Expand All @@ -63,15 +65,15 @@ fn main() {
let mut wrapped = bindings::ExampleSandbox { sb, rt };

let instance = bindings::component_sample::example::ExampleExports::adder(&mut wrapped);
let result = instance.add(1, 2);
let result = instance.add(1, 2).unwrap();
assert_eq!(3, result);
println!("Add result is {result}");
let result = instance.add(4, 3);
let result = instance.add(4, 3).unwrap();
assert_eq!(7, result);
println!("Add result is {result}");
instance.do_something(42);
instance.do_something(42).unwrap();

let result = instance.call_host("Hello".to_string());
let result = instance.call_host("Hello".to_string()).unwrap();
assert_eq!("Hello from component and the host!", result);
print!("Host Component interaction: {result}")
}
13 changes: 8 additions & 5 deletions src/hyperlight_wasm/examples/component_greeter_example/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl State {
}

// Same Host trait as component_example — shared interface across worlds
impl bindings::component_sample::example::Host for State {
impl bindings::component_sample::example::Host<hyperlight_common::component::Negative> for State {
fn r#print(&mut self, message: alloc::string::String) {
println!("[log] {message}");
}
Expand All @@ -45,7 +45,10 @@ impl bindings::component_sample::example::Host for State {
}

#[allow(refining_impl_trait)]
impl bindings::component_sample::example::GreeterWorldImports for State {
impl
bindings::component_sample::example::GreeterWorldImports<hyperlight_common::component::Negative>
for State
{
type Host = State;

fn r#host(&mut self) -> &mut Self {
Expand All @@ -61,7 +64,7 @@ fn main() {
.with_guest_scratch_size(100 * 1024 * 1024)
.build()
.unwrap();
let rt = bindings::register_host_functions(&mut sb, state);
let rt = bindings::register_host_functions(&mut sb, state).unwrap();

let sb = sb.load_runtime().unwrap();

Expand All @@ -72,11 +75,11 @@ fn main() {

let instance = bindings::component_sample::example::GreeterWorldExports::greeter(&mut wrapped);

let result = instance.greet("World".to_string());
let result = instance.greet("World".to_string()).unwrap();
assert_eq!("Hello World!", result);
println!("Greet result: {result}");

let result = instance.greet("Hyperlight".to_string());
let result = instance.greet("Hyperlight".to_string()).unwrap();
assert_eq!("Hello Hyperlight!", result);
println!("Greet result: {result}");
}
24 changes: 15 additions & 9 deletions src/hyperlight_wasm/examples/interruption/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ fn main() -> Result<()> {
let mut loaded = wasm_sandbox.load_module(mod_path)?;

println!("1. Sandbox created and module loaded");
assert!(!loaded.is_poisoned()?);
println!(" is_poisoned: {}", loaded.is_poisoned()?);
assert!(!loaded.status()?.is_poisoned());
println!(" is_poisoned: {}", loaded.status()?.is_poisoned());

// Take a snapshot before we do anything
let snapshot = loaded.snapshot()?;
Expand Down Expand Up @@ -81,7 +81,7 @@ fn main() -> Result<()> {
}

println!("\n5. Checking sandbox state after interruption:");
println!(" is_poisoned: {}", loaded.is_poisoned()?);
println!(" is_poisoned: {}", loaded.status()?.is_poisoned());

// Demonstrate that calling a poisoned sandbox fails
println!("\n6. Attempting to call guest function on poisoned sandbox...");
Expand All @@ -98,8 +98,11 @@ fn main() -> Result<()> {
// Recovery option 1: Use restore() to recover the sandbox
println!("\n7. Recovering sandbox using restore()...");
loaded.restore(snapshot.clone())?;
assert!(!loaded.is_poisoned()?);
println!(" is_poisoned after restore: {}", loaded.is_poisoned()?);
assert!(!loaded.status()?.is_poisoned());
println!(
" is_poisoned after restore: {}",
loaded.status()?.is_poisoned()
);

// Now we can call guest functions again
println!("\n8. Calling guest function after recovery...");
Expand All @@ -117,8 +120,11 @@ fn main() -> Result<()> {
});
let _ = loaded.call_guest_function::<i32>("KeepCPUBusy", 100000i32);

assert!(loaded.is_poisoned()?);
println!(" Sandbox poisoned again {}", loaded.is_poisoned()?);
assert!(loaded.status()?.is_poisoned());
println!(
" Sandbox poisoned again {}",
loaded.status()?.is_poisoned()
);

// unload_module() will recover the sandbox
let wasm_sandbox = loaded.unload_module()?;
Expand All @@ -127,10 +133,10 @@ fn main() -> Result<()> {
// Load a different module and continue
let hello_path = get_wasm_module_path("HelloWorld.aot")?;
let mut new_loaded = wasm_sandbox.load_module(hello_path)?;
assert!(!new_loaded.is_poisoned()?);
assert!(!new_loaded.status()?.is_poisoned());
println!(
" New module loaded, is_poisoned: {}",
new_loaded.is_poisoned()?
new_loaded.status()?.is_poisoned()
);

let result: i32 =
Expand Down
2 changes: 2 additions & 0 deletions src/hyperlight_wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub use hyperlight_host::hypervisor::InterruptHandle;
pub use hyperlight_host::is_hypervisor_present;
/// Create a generic HyperlightError
pub use hyperlight_host::new_error;
/// The lifecycle state of a sandbox.
pub use hyperlight_host::sandbox::SandboxStatus;
/// A snapshot of the memory of a sandbox at a given point in time.
pub use hyperlight_host::sandbox::snapshot::Snapshot;
/// OCI Image Layout reference types used by [`Snapshot::save`] /
Expand Down
20 changes: 15 additions & 5 deletions src/hyperlight_wasm/src/sandbox/loaded_wasm_sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use std::sync::Arc;

use hyperlight_host::func::{ParameterTuple, SupportedReturnType};
use hyperlight_host::hypervisor::InterruptHandle;
use hyperlight_host::sandbox::Callable;
use hyperlight_host::sandbox::snapshot::Snapshot;
use hyperlight_host::sandbox::{Callable, SandboxStatus};
use hyperlight_host::{MultiUseSandbox, Result, log_then_return, new_error};

use super::metrics::METRIC_TOTAL_LOADED_WASM_SANDBOXES;
Expand Down Expand Up @@ -160,6 +160,18 @@ impl LoadedWasmSandbox {
}
}

/// Get the current lifecycle state of the sandbox.
///
/// # Errors
///
/// Returns an error if the sandbox is in an invalid state.
pub fn status(&self) -> Result<SandboxStatus> {
match &self.inner {
Some(inner) => Ok(inner.status()),
None => log_then_return!("No inner MultiUseSandbox to check status"),
}
}

/// Check if the sandbox is in a poisoned state.
///
/// A sandbox becomes poisoned when guest execution does not complete normally,
Expand All @@ -183,11 +195,9 @@ impl LoadedWasmSandbox {
/// - `Ok(true)` if the sandbox is poisoned and needs recovery
/// - `Ok(false)` if the sandbox is healthy and can execute guest functions
/// - `Err` if the sandbox is in an invalid state
#[deprecated(since = "0.14.0", note = "use status().is_poisoned() instead")]
pub fn is_poisoned(&self) -> Result<bool> {
Comment thread
jsturtevant marked this conversation as resolved.
match &self.inner {
Some(inner) => Ok(inner.poisoned()),
None => log_then_return!("No inner MultiUseSandbox to check poisoned state"),
}
Ok(self.status()?.is_poisoned())
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ mod tests {

// Verify sandbox is poisoned after interruption
assert!(
loaded.is_poisoned()?,
loaded.status()?.is_poisoned(),
"Sandbox should be poisoned after interruption"
);

Expand All @@ -420,7 +420,7 @@ mod tests {

// Verify sandbox is not poisoned initially
assert!(
!loaded.is_poisoned()?,
!loaded.status()?.is_poisoned(),
"Sandbox should not be poisoned initially"
);

Expand All @@ -436,7 +436,7 @@ mod tests {

// Verify sandbox is now poisoned
assert!(
loaded.is_poisoned()?,
loaded.status()?.is_poisoned(),
"Sandbox should be poisoned after interruption"
);

Expand Down Expand Up @@ -543,13 +543,13 @@ mod tests {
// Call will be interrupted, poisoning the sandbox
let _ = loaded.call_guest_function::<i32>("KeepCPUBusy", 100000i32);

assert!(loaded.is_poisoned()?, "Sandbox should be poisoned");
assert!(loaded.status()?.is_poisoned(), "Sandbox should be poisoned");

// Restore should recover the sandbox
loaded.restore(snapshot)?;

assert!(
!loaded.is_poisoned()?,
!loaded.status()?.is_poisoned(),
"Sandbox should not be poisoned after restore"
);

Expand Down Expand Up @@ -583,7 +583,7 @@ mod tests {
// Call will be interrupted, poisoning the sandbox
let _ = loaded.call_guest_function::<i32>("KeepCPUBusy", 100000i32);

assert!(loaded.is_poisoned()?, "Sandbox should be poisoned");
assert!(loaded.status()?.is_poisoned(), "Sandbox should be poisoned");

// unload_module should recover the sandbox (it calls restore internally)
let wasm_sandbox = loaded.unload_module()?;
Expand All @@ -593,7 +593,7 @@ mod tests {
let mut new_loaded = wasm_sandbox.load_module(helloworld_wasm)?;

assert!(
!new_loaded.is_poisoned()?,
!new_loaded.status()?.is_poisoned(),
"New sandbox should not be poisoned"
);

Expand Down
2 changes: 1 addition & 1 deletion src/hyperlight_wasm_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ pub fn wasm_guest_bindgen(_: proc_macro::TokenStream) -> proc_macro::TokenStream
// stream directly and emitting an include!() pointing at a
// temporary file, depending on whether the user has requested
// a debug temporary file be created.
util::emit_decls(decls).into()
util::emit_decls(decls, &kebab_name).into()
})
}
7 changes: 3 additions & 4 deletions src/hyperlight_wasm_macro/src/wasmguest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,13 @@ fn emit_component<'b>(s: &mut State<'_, 'b>, wn: WitName, ct: &Component<'b>) ->
let r#trait = kebab_to_type(wn.name);
let import_trait = format_ident!("{}Imports", r#trait);
let export_trait = format_ident!("{}Exports", r#trait);
s.import_param_var = Some(format_ident!("I"));
s.self_param_var = Some(format_ident!("S"));
s.positivity_param = Some(quote! { ::hyperlight_common::component::Positive });

resource::emit_tables(
&mut s,
format_ident!("{}Resources", kebab_to_type(wn.name)),
quote! { #ns::#import_trait + ::core::marker::Send + 'static },
Some(quote! { #ns::#export_trait<I> }),
quote! { #ns::#import_trait<::hyperlight_common::component::Negative> + ::core::marker::Send + 'static },
Some(quote! { #ns::#export_trait<::hyperlight_common::component::Positive, I> }),
true,
);
s.root_mod
Expand Down
Loading