Skip to main content

MultiUseSandbox

Struct MultiUseSandbox 

Source
pub struct MultiUseSandbox { /* private fields */ }
Expand description

A fully initialized sandbox that can execute guest functions multiple times.

Guest functions can be called repeatedly while maintaining state between calls.

Post-Stage-F: the upstream snapshot() / restore() / map_file_cow() rollback machinery is gone along with the CoW PT marking that backed it. If a guest call fails for any reason, drop the sandbox and build a new one — that’s the only recovery path now (and the one nub already used).

Implementations§

Source§

impl MultiUseSandbox

Source

pub fn id(&self) -> u64

Returns this sandbox’s unique id.

Source

pub fn vcpu_count(&self) -> Result<usize>

Fixed vCPU pool size configured for this sandbox.

Source

pub fn call_raw(&self, fn_id: u32, payload: &[u8]) -> Result<Vec<u8>>

Call a guest function by fn_id with a raw byte payload. Returns the response payload bytes on success.

Wire format: the host serialises a [nub_host_common::rpc::Request] (rkyv) carrying fn_id and payload, ships it via the input data ring, the guest decodes

  • dispatches + writes a Response to the output ring, and we read + check status before returning the inner payload.

Changes made to the sandbox during execution are persisted. On failure the sandbox should be dropped and rebuilt.

Source

pub fn call_raw_on_vcpu( &self, vcpu_index: usize, fn_id: u32, payload: &[u8], ) -> Result<Vec<u8>>

Serialized control-plane call on a selected vCPU lane. This still uses the legacy shared input/output rings and therefore must not be used as the concurrent invoke mechanism; it exists to validate and bootstrap non-primary lanes. Concurrent invokes use the per-lane worker slots.

Source

pub fn invoke_cached_parallel( &self, job_id: u64, packet: &InvokePacket, ) -> Result<InvocationResult>

Submit an invoke packet through the per-lane parallel worker slots.

Workers are started lazily and remain hot for subsequent invoke calls. The legacy raw RPC channel remains the serialized control plane. User job waits deliberately have no host-side timeout; without a cancellation API, the lane must stay reserved until the guest reports completion or the worker exits.

Source

pub fn evict_jit_all_parallel(&self) -> Result<()>

Bench-only: evict guest JIT caches while keeping the hot invoke worker pool alive. The legacy raw RPC path stops workers before entering the shared control ring; cold benchmarks call this every iteration, so using the worker slot protocol avoids measuring worker teardown/startup.

All lanes are reserved first. That preserves the eviction invariant: no frame runtime can be live while image arenas and templates are dropped.

Source

pub fn put_cap(&self, cap: &Cap) -> Result<AbiCapHash>

Publish a [Cap] into the guest’s heap-resident cap directory via the [FN_ID_NUB_PUT_CAP] RPC.

rkyv-encodes cap directly via [rkyv::to_bytes]; the resulting bytes are shipped via Self::call_raw and the guest-computed CapHash is read back. On the guest side, the cap is inserted into the nub_arch_x86::state_cache::DIRECTORY map, keyed by hash.

Caps whose graph still holds a CapHashOrRef::Ref target (cache-local lifetime handles with no resolution on the receive side) fail at rkyv-encode with a typed CapHasRefError wrapped in the rancor error chain. Other encode/decode failures are surfaced as HyperlightError::Error. A sentinel response (all-0xFF hash) from the guest is also turned into an error.

Source

pub fn put_cap_with_hash(&self, hash: AbiCapHash, cap: &Cap) -> Result<()>

Pre-hashed put: idempotent fast path that short-circuits the full Self::put_cap RPC when this sandbox has already published hash.

Behaviour:

  • If hash is in the host-side published_blobs set, return immediately — we already shipped this cap and the blobs tier never evicts, so the guest still holds it. We skip the rkyv encode + VMEXIT + guest decode + merkle walk + directory insert. This is the hot path for bench loops that re-publish the same cap graph every iteration.
  • Otherwise, ship put_cap(cap), debug-assert the returned hash matches hash, and record it.

We deliberately do not check the guest’s directory directly: the guest’s CacheDirectory is a hashbrown table built with a different SIMD Group width than the host’s hashbrown (see published_blobs), so a host-side deref of it is unsound.

Source

pub fn interrupt_handle(&self) -> Arc<dyn InterruptHandle>

Returns a handle for interrupting guest execution.

Trait Implementations§

Source§

impl Debug for MultiUseSandbox

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Registerable for MultiUseSandbox

Allow registering host functions on an already-evolved crate::MultiUseSandbox.

The primary entry point for host-function registration is the UninitializedSandbox impl above — that’s the lifecycle phase where the guest hasn’t yet been allowed to issue host calls. There are, however, cases where a MultiUseSandbox is obtained without traversing the Uninitialized → evolve() path:

  • Sandboxes loaded from a persisted snapshot.
  • Any future API that yields a MultiUseSandbox directly.

In those cases the caller never had a chance to call register_host_function on an UninitializedSandbox, so we expose the same trait implementation here for late registration. The guest’s dispatcher resolves by fn_id at call time, so inserting into the registry after evolve() is semantically safe as long as the first host-function invocation happens after registration completes.

Source§

fn register_host_function(&mut self, fn_id: u32, func: HostFn) -> Result<()>

Register func to be invoked by the guest under the given fn_id. Overwrites any prior entry for that id.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> ArchivePointee for T

§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> LayoutRaw for T

§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
§

impl<T> Pointee for T

§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more