Skip to content

Commit 65ff6ff

Browse files
committed
bring back the previous call_guest_function_by_name behavior
Signed-off-by: Jorge Prendes <[email protected]>
1 parent 9ad8569 commit 65ff6ff

File tree

3 files changed

+92
-11
lines changed

3 files changed

+92
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn main() -> hyperlight_host::Result<()> {
5858
let message = "Hello, World! I am executing inside of a VM :)\n".to_string();
5959
// in order to call a function it first must be defined in the guest and exposed so that
6060
// the host can call it
61-
multi_use_sandbox.call_guest_function_by_name::<i32>(
61+
multi_use_sandbox.run::<i32>(
6262
"PrintOutput",
6363
message,
6464
)?;

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub struct MultiUseSandbox {
6363
dispatch_ptr: RawPtr,
6464
#[cfg(gdb)]
6565
dbg_mem_access_fn: DbgMemAccessHandlerWrapper,
66+
snapshot: Option<Snapshot>,
6667
}
6768

6869
impl MultiUseSandbox {
@@ -87,6 +88,7 @@ impl MultiUseSandbox {
8788
dispatch_ptr,
8889
#[cfg(gdb)]
8990
dbg_mem_access_fn,
91+
snapshot: None,
9092
}
9193
}
9294

@@ -122,7 +124,7 @@ impl MultiUseSandbox {
122124
.unwrap_mgr_mut()
123125
.snapshot(self.id, mapped_regions_vec)?;
124126
Ok(Snapshot {
125-
inner: memory_snapshot,
127+
inner: Arc::new(memory_snapshot),
126128
})
127129
}
128130

@@ -181,12 +183,15 @@ impl MultiUseSandbox {
181183
unsafe { self.vm.map_region(region)? };
182184
}
183185

186+
// The restored snapshot is now our most current snapshot
187+
self.snapshot = Some(snapshot.clone());
188+
184189
Ok(())
185190
}
186191

187192
/// Calls a guest function by name with the specified arguments.
188193
///
189-
/// Changes made to the sandbox during execution are persisted.
194+
/// Changes made to the sandbox during execution are *not* persisted.
190195
///
191196
/// # Examples
192197
///
@@ -215,12 +220,65 @@ impl MultiUseSandbox {
215220
/// # Ok(())
216221
/// # }
217222
/// ```
223+
#[doc(hidden)]
224+
#[deprecated(
225+
since = "0.8.0",
226+
note = "Deprecated in favour or call and snapshot/restore."
227+
)]
218228
#[instrument(err(Debug), skip(self, args), parent = Span::current())]
219229
pub fn call_guest_function_by_name<Output: SupportedReturnType>(
220230
&mut self,
221231
func_name: &str,
222232
args: impl ParameterTuple,
223233
) -> Result<Output> {
234+
let snapshot = match &self.snapshot {
235+
Some(snapshot) => snapshot.clone(),
236+
None => self.snapshot()?,
237+
};
238+
let res = self.run(func_name, args);
239+
self.restore(&snapshot)?;
240+
res
241+
}
242+
243+
/// Calls a guest function by name with the specified arguments.
244+
///
245+
/// Changes made to the sandbox during execution are persisted.
246+
///
247+
/// # Examples
248+
///
249+
/// ```no_run
250+
/// # use hyperlight_host::{MultiUseSandbox, UninitializedSandbox, GuestBinary};
251+
/// # fn example() -> Result<(), Box<dyn std::error::Error>> {
252+
/// let mut sandbox: MultiUseSandbox = UninitializedSandbox::new(
253+
/// GuestBinary::FilePath("guest.bin".into()),
254+
/// None
255+
/// )?.evolve()?;
256+
///
257+
/// // Call function with no arguments
258+
/// let result: i32 = sandbox.call("GetCounter", ())?;
259+
///
260+
/// // Call function with single argument
261+
/// let doubled: i32 = sandbox.call("Double", 21)?;
262+
/// assert_eq!(doubled, 42);
263+
///
264+
/// // Call function with multiple arguments
265+
/// let sum: i32 = sandbox.call("Add", (10, 32))?;
266+
/// assert_eq!(sum, 42);
267+
///
268+
/// // Call function returning string
269+
/// let message: String = sandbox.call("Echo", "Hello, World!".to_string())?;
270+
/// assert_eq!(message, "Hello, World!");
271+
/// # Ok(())
272+
/// # }
273+
/// ```
274+
#[instrument(err(Debug), skip(self, args), parent = Span::current())]
275+
pub fn run<Output: SupportedReturnType>(
276+
&mut self,
277+
func_name: &str,
278+
args: impl ParameterTuple,
279+
) -> Result<Output> {
280+
// Reset snapshot since we are mutating the sandbox state
281+
self.snapshot = None;
224282
maybe_time_and_emit_guest_call(func_name, || {
225283
let ret = self.call_guest_function_by_name_no_reset(
226284
func_name,
@@ -429,9 +487,33 @@ mod tests {
429487
use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags, MemoryRegionType};
430488
#[cfg(target_os = "linux")]
431489
use crate::mem::shared_mem::{ExclusiveSharedMemory, GuestSharedMemory, SharedMemory as _};
432-
use crate::sandbox::{Callable, SandboxConfiguration};
490+
use crate::sandbox::{Callable as _, SandboxConfiguration};
433491
use crate::{GuestBinary, HyperlightError, MultiUseSandbox, Result, UninitializedSandbox};
434492

493+
/// Tests that call_guest_function_by_name restores the state correctly
494+
#[test]
495+
fn test_call_guest_function_by_name() {
496+
let mut sbox: MultiUseSandbox = {
497+
let path = simple_guest_as_string().unwrap();
498+
let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap();
499+
u_sbox.evolve()
500+
}
501+
.unwrap();
502+
503+
let snapshot = sbox.snapshot().unwrap();
504+
505+
let _ = sbox.run::<i32>("AddToStatic", 5i32).unwrap();
506+
let res: i32 = sbox.run("GetStatic", ()).unwrap();
507+
assert_eq!(res, 5);
508+
509+
sbox.restore(&snapshot).unwrap();
510+
#[allow(deprecated)]
511+
let _ = sbox.call_guest_function_by_name::<i32>("AddToStatic", 5i32).unwrap();
512+
#[allow(deprecated)]
513+
let res: i32 = sbox.call_guest_function_by_name("GetStatic", ()).unwrap();
514+
assert_eq!(res, 0);
515+
}
516+
435517
// Tests to ensure that many (1000) function calls can be made in a call context with a small stack (1K) and heap(14K).
436518
// This test effectively ensures that the stack is being properly reset after each call and we are not leaking memory in the Guest.
437519
#[test]
@@ -481,15 +563,13 @@ mod tests {
481563

482564
let snapshot = sbox.snapshot().unwrap();
483565

484-
let _ = sbox
485-
.call_guest_function_by_name::<i32>("AddToStatic", 5i32)
486-
.unwrap();
566+
let _ = sbox.run::<i32>("AddToStatic", 5i32).unwrap();
487567

488-
let res: i32 = sbox.call_guest_function_by_name("GetStatic", ()).unwrap();
568+
let res: i32 = sbox.run("GetStatic", ()).unwrap();
489569
assert_eq!(res, 5);
490570

491571
sbox.restore(&snapshot).unwrap();
492-
let res: i32 = sbox.call_guest_function_by_name("GetStatic", ()).unwrap();
572+
let res: i32 = sbox.run("GetStatic", ()).unwrap();
493573
assert_eq!(res, 0);
494574
}
495575

src/hyperlight_host/src/sandbox/snapshot.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17+
use std::sync::Arc;
18+
1719
use crate::mem::shared_mem_snapshot::SharedMemorySnapshot;
1820

1921
/// A snapshot capturing the state of the memory in a `MultiUseSandbox`.
2022
#[derive(Clone)]
2123
pub struct Snapshot {
22-
// TODO: Use Arc<SharedMemorySnapshot>
23-
pub(crate) inner: SharedMemorySnapshot,
24+
pub(crate) inner: Arc<SharedMemorySnapshot>,
2425
}

0 commit comments

Comments
 (0)