@@ -67,6 +67,7 @@ pub struct MultiUseSandbox {
6767 dispatch_ptr : RawPtr ,
6868 #[ cfg( gdb) ]
6969 dbg_mem_access_fn : DbgMemAccessHandlerWrapper ,
70+ snapshot : Option < Snapshot > ,
7071}
7172
7273impl MultiUseSandbox {
@@ -91,6 +92,7 @@ impl MultiUseSandbox {
9192 dispatch_ptr,
9293 #[ cfg( gdb) ]
9394 dbg_mem_access_fn,
95+ snapshot : None ,
9496 }
9597 }
9698
@@ -104,7 +106,7 @@ impl MultiUseSandbox {
104106 . unwrap_mgr_mut ( )
105107 . snapshot ( self . id , mapped_regions_vec) ?;
106108 Ok ( Snapshot {
107- inner : memory_snapshot,
109+ inner : Arc :: new ( memory_snapshot) ,
108110 } )
109111 }
110112
@@ -133,17 +135,43 @@ impl MultiUseSandbox {
133135 unsafe { self . vm . map_region ( region) ? } ;
134136 }
135137
138+ // The restored snapshot is now our most current snapshot
139+ self . snapshot = Some ( snapshot. clone ( ) ) ;
140+
136141 Ok ( ( ) )
137142 }
138143
139144 /// Call a guest function by name, with the given return type and arguments.
140- /// The changes made to the sandbox are persisted
145+ /// The changes made to the sandbox are **not** persisted
146+ #[ deprecated(
147+ since = "0.8.0" ,
148+ note = "Deprecated in favour or call_guest and snapshot/restore."
149+ ) ]
141150 #[ instrument( err( Debug ) , skip( self , args) , parent = Span :: current( ) ) ]
142151 pub fn call_guest_function_by_name < Output : SupportedReturnType > (
143152 & mut self ,
144153 func_name : & str ,
145154 args : impl ParameterTuple ,
146155 ) -> Result < Output > {
156+ let snapshot = match & self . snapshot {
157+ Some ( snapshot) => snapshot. clone ( ) ,
158+ None => self . snapshot ( ) ?,
159+ } ;
160+ let res = self . run ( func_name, args) ;
161+ self . restore ( & snapshot) ?;
162+ res
163+ }
164+
165+ /// Call a guest function by name, with the given return type and arguments.
166+ /// The changes made to the sandbox are persisted
167+ #[ instrument( err( Debug ) , skip( self , args) , parent = Span :: current( ) ) ]
168+ pub fn run < Output : SupportedReturnType > (
169+ & mut self ,
170+ func_name : & str ,
171+ args : impl ParameterTuple ,
172+ ) -> Result < Output > {
173+ // Reset snapshot since we are mutating the sandbox state
174+ self . snapshot = None ;
147175 maybe_time_and_emit_guest_call ( func_name, || {
148176 let ret = self . call_guest_function_by_name_no_reset (
149177 func_name,
@@ -326,9 +354,33 @@ mod tests {
326354 use crate :: mem:: memory_region:: { MemoryRegion , MemoryRegionFlags , MemoryRegionType } ;
327355 #[ cfg( target_os = "linux" ) ]
328356 use crate :: mem:: shared_mem:: { ExclusiveSharedMemory , GuestSharedMemory , SharedMemory as _} ;
329- use crate :: sandbox:: { Callable , SandboxConfiguration } ;
357+ use crate :: sandbox:: { Callable as _ , SandboxConfiguration } ;
330358 use crate :: { GuestBinary , HyperlightError , MultiUseSandbox , Result , UninitializedSandbox } ;
331359
360+ /// Tests that call_guest_function_by_name restores the state correctly
361+ #[ test]
362+ fn test_call_guest_function_by_name ( ) {
363+ let mut sbox: MultiUseSandbox = {
364+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
365+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
366+ u_sbox. evolve ( )
367+ }
368+ . unwrap ( ) ;
369+
370+ let snapshot = sbox. snapshot ( ) . unwrap ( ) ;
371+
372+ let _ = sbox. run :: < i32 > ( "AddToStatic" , 5i32 ) . unwrap ( ) ;
373+ let res: i32 = sbox. run ( "GetStatic" , ( ) ) . unwrap ( ) ;
374+ assert_eq ! ( res, 5 ) ;
375+
376+ sbox. restore ( & snapshot) . unwrap ( ) ;
377+ #[ allow( deprecated) ]
378+ let _ = sbox. call_guest_function_by_name :: < i32 > ( "AddToStatic" , 5i32 ) . unwrap ( ) ;
379+ #[ allow( deprecated) ]
380+ let res: i32 = sbox. call_guest_function_by_name ( "GetStatic" , ( ) ) . unwrap ( ) ;
381+ assert_eq ! ( res, 0 ) ;
382+ }
383+
332384 // Tests to ensure that many (1000) function calls can be made in a call context with a small stack (1K) and heap(14K).
333385 // This test effectively ensures that the stack is being properly reset after each call and we are not leaking memory in the Guest.
334386 #[ test]
@@ -378,15 +430,13 @@ mod tests {
378430
379431 let snapshot = sbox. snapshot ( ) . unwrap ( ) ;
380432
381- let _ = sbox
382- . call_guest_function_by_name :: < i32 > ( "AddToStatic" , 5i32 )
383- . unwrap ( ) ;
433+ let _ = sbox. run :: < i32 > ( "AddToStatic" , 5i32 ) . unwrap ( ) ;
384434
385- let res: i32 = sbox. call_guest_function_by_name ( "GetStatic" , ( ) ) . unwrap ( ) ;
435+ let res: i32 = sbox. run ( "GetStatic" , ( ) ) . unwrap ( ) ;
386436 assert_eq ! ( res, 5 ) ;
387437
388438 sbox. restore ( & snapshot) . unwrap ( ) ;
389- let res: i32 = sbox. call_guest_function_by_name ( "GetStatic" , ( ) ) . unwrap ( ) ;
439+ let res: i32 = sbox. run ( "GetStatic" , ( ) ) . unwrap ( ) ;
390440 assert_eq ! ( res, 0 ) ;
391441 }
392442
0 commit comments