Skip to content

Commit 030fbb5

Browse files
committed
fixup! Change sandbox restore to be a bit more judicious about when to restore
A few minor nits/documentation fixes/formatting fixes/cleanups Signed-off-by: Lucy Menon <168595099+syntactically@users.noreply.github.com>
1 parent 948406e commit 030fbb5

2 files changed

Lines changed: 63 additions & 10 deletions

File tree

src/hyperlight_wasm/src/sandbox/loaded_wasm_sandbox.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,14 @@ impl LoadedWasmSandbox {
112112
}
113113
}
114114

115-
/// Unload the wasm module and return a `WasmSandbox` that can be used to load another module.
115+
/// Unload the wasm module and return a `WasmSandbox` that can be
116+
/// used to load another module.
116117
///
117-
/// This method internally calls [`restore()`](Self::restore) to reset the sandbox to its
118-
/// pre-module state, which also clears any poisoned state. This means `unload_module()`
119-
/// can be called on a poisoned sandbox to recover it.
118+
/// This method defers calling [`restore()`](Self::restore) to
119+
/// reset the sandbox to its pre-module state until a new module
120+
/// is loaded. However, the sandbox will always be restored when a
121+
/// new module is loaded, so a poisoned sandbox can be recovered
122+
/// by unloading and reloading a module.
120123
pub fn unload_module(mut self) -> Result<WasmSandbox> {
121124
let sandbox = self
122125
.inner

src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,15 @@ impl WasmSandbox {
8080

8181
fn restore_if_needed(&mut self) -> Result<()> {
8282
if self.needs_restore {
83-
self.inner.as_mut().ok_or(new_error!("WasmSandbox is none"))?.restore(self.snapshot.as_ref().ok_or(new_error!("Snapshot is none"))?.clone())?;
83+
self.inner
84+
.as_mut()
85+
.ok_or(new_error!("WasmSandbox is none"))?
86+
.restore(
87+
self.snapshot
88+
.as_ref()
89+
.ok_or(new_error!("Snapshot is none"))?
90+
.clone(),
91+
)?;
8492
self.needs_restore = false;
8593
}
8694
Ok(())
@@ -111,12 +119,13 @@ impl WasmSandbox {
111119
/// Load a Wasm module by restoring a Hyperlight snapshot taken
112120
/// from a `LoadedWasmSandbox`.
113121
pub fn load_from_snapshot(mut self, snapshot: Arc<Snapshot>) -> Result<LoadedWasmSandbox> {
114-
let mut sb = self.inner.take().unwrap();
122+
let sb = self
123+
.inner
124+
.as_mut()
125+
.ok_or_else(|| new_error!("WasmSandbox is None"))?;
115126
sb.restore(snapshot)?;
116-
LoadedWasmSandbox::new(
117-
sb,
118-
self.snapshot.take().unwrap(),
119-
)
127+
128+
self.finalize_module_load()
120129
}
121130

122131
/// Load a Wasm module that is currently present in a buffer in
@@ -165,6 +174,7 @@ impl WasmSandbox {
165174
/// Before you can call guest functions in the sandbox, you must call
166175
/// this function and use the returned value to call guest functions.
167176
pub fn load_module_from_buffer(mut self, buffer: &[u8]) -> Result<LoadedWasmSandbox> {
177+
self.restore_if_needed()?;
168178
let inner = self
169179
.inner
170180
.as_mut()
@@ -496,6 +506,46 @@ mod tests {
496506
}
497507
}
498508

509+
#[test]
510+
fn test_load_from_snapshot() {
511+
let mut sandbox = SandboxBuilder::new().build().unwrap();
512+
sandbox
513+
.register(
514+
"GetTimeSinceBootMicrosecond",
515+
get_time_since_boot_microsecond,
516+
)
517+
.unwrap();
518+
let sb = sandbox.load_runtime().unwrap();
519+
520+
let helloworld_wasm = get_test_file_path("HelloWorld.aot").unwrap();
521+
let runwasm_wasm = get_test_file_path("RunWasm.aot").unwrap();
522+
523+
// load one module, and make sure that a function in it
524+
// can be called
525+
let mut lb1 = sb.load_module(helloworld_wasm).unwrap();
526+
let result: i32 = lb1
527+
.call_guest_function("HelloWorld", "Message from Rust Test".to_string())
528+
.unwrap();
529+
assert_eq!(result, 0);
530+
let snapshot = lb1.snapshot().unwrap();
531+
532+
// load another module, and make sure that a function in
533+
// it can be called
534+
let sb = lb1.unload_module().unwrap();
535+
let mut lb2 = sb.load_module(runwasm_wasm).unwrap();
536+
let result: i32 = lb2.call_guest_function("CalcFib", 10i32).unwrap();
537+
assert_eq!(result, 55);
538+
539+
// reload the first module via snapshot, and make sure the
540+
// original function can be called again
541+
let sb = lb2.unload_module().unwrap();
542+
let mut lb3 = sb.load_from_snapshot(snapshot).unwrap();
543+
let result: i32 = lb3
544+
.call_guest_function("HelloWorld", "Message from Rust Test".to_string())
545+
.unwrap();
546+
assert_eq!(result, 0);
547+
}
548+
499549
#[test]
500550
fn test_load_module_buffer() {
501551
let sandboxes = get_test_wasm_sandboxes().unwrap();

0 commit comments

Comments
 (0)