Skip to content

Commit efb997f

Browse files
committed
feat(host): implement Registerable for MultiUseSandbox
The primary entry point for registering host functions is the UninitializedSandbox — that's the lifecycle phase where the guest hasn't yet been allowed to issue host calls, so the registry can be populated safely up front. 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. Today they have to drop down to internal fields or fork the registry manually. Extend the Registerable trait impl to MultiUseSandbox so late registration is a one-liner. Semantics are unchanged: the guest's dispatcher resolves host functions by name at call time, so inserting into the registry after evolve() is safe as long as the first host-call happens after registration completes. Also flips MultiUseSandbox.host_funcs from pub(super) to pub(crate) so the impl in src/func/host_functions.rs can reach it. Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent b45b363 commit efb997f

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

src/hyperlight_host/src/func/host_functions.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,46 @@ impl Registerable for UninitializedSandbox {
5656
}
5757
}
5858

59+
/// Allow registering host functions on an already-evolved
60+
/// [`crate::MultiUseSandbox`].
61+
///
62+
/// The primary entry point for host-function registration is the
63+
/// `UninitializedSandbox` impl above — that's the lifecycle phase
64+
/// where the guest hasn't yet been allowed to issue host calls.
65+
/// There are, however, cases where a `MultiUseSandbox` is obtained
66+
/// without traversing the `Uninitialized → evolve()` path:
67+
///
68+
/// - Sandboxes loaded from a persisted snapshot.
69+
/// - Any future API that yields a `MultiUseSandbox` directly.
70+
///
71+
/// In those cases the caller never had a chance to call
72+
/// `register_host_function` on an `UninitializedSandbox`, so we
73+
/// expose the same trait implementation here for late registration.
74+
/// The guest's host-function dispatcher resolves by name at call
75+
/// time, so inserting into the registry after `evolve()` is
76+
/// semantically safe as long as the first host-function invocation
77+
/// happens after registration completes.
78+
impl Registerable for crate::MultiUseSandbox {
79+
fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
80+
&mut self,
81+
name: &str,
82+
hf: impl Into<HostFunction<Output, Args>>,
83+
) -> Result<()> {
84+
let mut hfs = self
85+
.host_funcs
86+
.try_lock()
87+
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?;
88+
89+
let entry = FunctionEntry {
90+
function: hf.into().into(),
91+
parameter_types: Args::TYPE,
92+
return_type: Output::TYPE,
93+
};
94+
95+
(*hfs).register_host_function(name.to_string(), entry)
96+
}
97+
}
98+
5999
/// A representation of a host function.
60100
/// This is a thin wrapper around a `Fn(Args) -> Result<Output>`.
61101
#[derive(Clone)]

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub struct MultiUseSandbox {
8686
id: u64,
8787
/// Whether this sandbox is poisoned
8888
poisoned: bool,
89-
pub(super) host_funcs: Arc<Mutex<FunctionRegistry>>,
89+
pub(crate) host_funcs: Arc<Mutex<FunctionRegistry>>,
9090
pub(crate) mem_mgr: SandboxMemoryManager<HostSharedMemory>,
9191
vm: HyperlightVm,
9292
#[cfg(gdb)]

0 commit comments

Comments
 (0)