pub struct MultiUseSandbox { /* private fields */ }
Expand description
A sandbox that supports being used Multiple times. The implication of being used multiple times is two-fold:
-
The sandbox can be used to call guest functions multiple times, each time a guest function is called the state of the sandbox is reset to the state it was in before the call was made.
-
A MultiUseGuestCallContext can be created from the sandbox and used to make multiple guest function calls to the Sandbox. in this case the state of the sandbox is not reset until the context is finished and the
MultiUseSandbox
is returned.
Implementations§
Source§impl MultiUseSandbox
impl MultiUseSandbox
Sourcepub fn new_call_context(self) -> MultiUseGuestCallContext
pub fn new_call_context(self) -> MultiUseGuestCallContext
Create a new MultiUseCallContext
suitable for making 0 or more
calls to guest functions within the same context.
Since this function consumes self
, the returned
MultiUseGuestCallContext
is guaranteed mutual exclusion for calling
functions within the sandbox. This guarantee is enforced at compile
time, and no locks, atomics, or any other mutual exclusion mechanisms
are used at runtime.
If you have called this function, have a MultiUseGuestCallContext
,
and wish to “return” it to a MultiUseSandbox
, call the finish
method on the context.
Example usage (compiled as a “no_run” doctest since the test binary will not be found):
use hyperlight_host::sandbox::{UninitializedSandbox, MultiUseSandbox};
use hyperlight_common::flatbuffer_wrappers::function_types::{ReturnType, ParameterValue, ReturnValue};
use hyperlight_host::sandbox_state::sandbox::EvolvableSandbox;
use hyperlight_host::sandbox_state::transition::Noop;
use hyperlight_host::GuestBinary;
// First, create a new uninitialized sandbox, then evolve it to become
// an initialized, single-use one.
let u_sbox = UninitializedSandbox::new(
GuestBinary::FilePath("some_guest_binary".to_string()),
None,
).unwrap();
let sbox: MultiUseSandbox = u_sbox.evolve(Noop::default()).unwrap();
// Next, create a new call context from the single-use sandbox.
// After this line, your code will not compile if you try to use the
// original `sbox` variable.
let mut ctx = sbox.new_call_context();
// Do a guest call with the context. Assumes that the loaded binary
// ("some_guest_binary") has a function therein called "SomeGuestFunc"
// that takes a single integer argument and returns an integer.
match ctx.call(
"SomeGuestFunc",
ReturnType::Int,
Some(vec![ParameterValue::Int(1)])
) {
Ok(ReturnValue::Int(i)) => println!(
"got successful return value {}",
i,
),
other => panic!(
"failed to get return value as expected ({:?})",
other,
),
};
// You can make further calls with the same context if you want.
// Otherwise, `ctx` will be dropped and all resources, including the
// underlying `MultiUseSandbox`, will be released and no further
// contexts can be created from that sandbox.
//
// If you want to avoid
// that behavior, call `finish` to convert the context back to
// the original `MultiUseSandbox`, as follows:
let _orig_sbox = ctx.finish();
// Now, you can operate on the original sandbox again (i.e. add more
// host functions etc...), create new contexts, and so on.
Sourcepub fn call_guest_function_by_name<Output: SupportedReturnType>(
&mut self,
func_name: &str,
args: impl ParameterTuple,
) -> Result<Output>
pub fn call_guest_function_by_name<Output: SupportedReturnType>( &mut self, func_name: &str, args: impl ParameterTuple, ) -> Result<Output>
Call a guest function by name, with the given return type and arguments.
Sourcepub fn interrupt_handle(&self) -> Arc<dyn InterruptHandle>
pub fn interrupt_handle(&self) -> Arc<dyn InterruptHandle>
Get a handle to the interrupt handler for this sandbox, capable of interrupting guest execution.
Trait Implementations§
Source§impl Debug for MultiUseSandbox
impl Debug for MultiUseSandbox
Source§impl DevolvableSandbox<MultiUseSandbox, MultiUseSandbox, Noop<MultiUseSandbox, MultiUseSandbox>> for MultiUseSandbox
impl DevolvableSandbox<MultiUseSandbox, MultiUseSandbox, Noop<MultiUseSandbox, MultiUseSandbox>> for MultiUseSandbox
Source§fn devolve(
self,
_tsn: Noop<MultiUseSandbox, MultiUseSandbox>,
) -> Result<MultiUseSandbox>
fn devolve( self, _tsn: Noop<MultiUseSandbox, MultiUseSandbox>, ) -> Result<MultiUseSandbox>
Consume self
and move it back to a MultiUseSandbox
with previous state.
The purpose of this function is to allow multiple states to be associated with a single MultiUseSandbox.
An implementation such as HyperlightJs or HyperlightWasm can use this to call guest functions to load JS or WASM code and then evolve the sandbox causing state to be captured. The new MultiUseSandbox can then be used to call guest functions to execute the loaded code. The devolve can be used to return the MultiUseSandbox to the state before the code was loaded. Thus avoiding initialisation overhead
Source§impl<'a, F> EvolvableSandbox<MultiUseSandbox, MultiUseSandbox, MultiUseContextCallback<'a, MultiUseSandbox, F>> for MultiUseSandbox
impl<'a, F> EvolvableSandbox<MultiUseSandbox, MultiUseSandbox, MultiUseContextCallback<'a, MultiUseSandbox, F>> for MultiUseSandbox
Source§fn evolve(
self,
transition_func: MultiUseContextCallback<'a, MultiUseSandbox, F>,
) -> Result<MultiUseSandbox>
fn evolve( self, transition_func: MultiUseContextCallback<'a, MultiUseSandbox, F>, ) -> Result<MultiUseSandbox>
The purpose of this function is to allow multiple states to be associated with a single MultiUseSandbox.
An implementation such as HyperlightJs or HyperlightWasm can use this to call guest functions to load JS or WASM code and then evolve the sandbox causing state to be captured. The new MultiUseSandbox can then be used to call guest functions to execute the loaded code.
The evolve function creates a new MultiUseCallContext which is then passed to a callback function allowing the callback function to call guest functions as part of the evolve process, once the callback function is complete the context is finished using a crate internal method that does not restore the prior state of the Sandbox. It then creates a mew memory snapshot on the snapshot stack and returns the MultiUseSandbox
Source§impl EvolvableSandbox<UninitializedSandbox, MultiUseSandbox, Noop<UninitializedSandbox, MultiUseSandbox>> for UninitializedSandbox
impl EvolvableSandbox<UninitializedSandbox, MultiUseSandbox, Noop<UninitializedSandbox, MultiUseSandbox>> for UninitializedSandbox
Source§fn evolve(
self,
_: Noop<UninitializedSandbox, MultiUseSandbox>,
) -> Result<MultiUseSandbox>
fn evolve( self, _: Noop<UninitializedSandbox, MultiUseSandbox>, ) -> Result<MultiUseSandbox>
Evolve self
to a MultiUseSandbox
without any additional metadata.