@@ -67,6 +67,8 @@ pub struct MultiUseSandbox {
6767 dispatch_ptr : RawPtr ,
6868 #[ cfg( gdb) ]
6969 dbg_mem_access_fn : DbgMemAccessHandlerWrapper ,
70+ /// If the current state of the sandbox has been captured in a snapshot,
71+ /// that snapshot is stored here.
7072 snapshot : Option < Snapshot > ,
7173}
7274
@@ -99,20 +101,31 @@ impl MultiUseSandbox {
99101 /// Create a snapshot of the current state of the sandbox's memory.
100102 #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) ) ]
101103 pub fn snapshot ( & mut self ) -> Result < Snapshot > {
104+ if let Some ( snapshot) = & self . snapshot {
105+ return Ok ( snapshot. clone ( ) ) ;
106+ }
102107 let mapped_regions_iter = self . vm . get_mapped_regions ( ) ;
103108 let mapped_regions_vec: Vec < MemoryRegion > = mapped_regions_iter. cloned ( ) . collect ( ) ;
104109 let memory_snapshot = self
105110 . mem_mgr
106111 . unwrap_mgr_mut ( )
107112 . snapshot ( self . id , mapped_regions_vec) ?;
108- Ok ( Snapshot {
109- inner : Arc :: new ( memory_snapshot) ,
110- } )
113+ let inner = Arc :: new ( memory_snapshot) ;
114+ let snapshot = Snapshot { inner } ;
115+ self . snapshot = Some ( snapshot. clone ( ) ) ;
116+ Ok ( snapshot)
111117 }
112118
113119 /// Restore the sandbox's memory to the state captured in the given snapshot.
114120 #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) ) ]
115121 pub fn restore ( & mut self , snapshot : & Snapshot ) -> Result < ( ) > {
122+ if let Some ( snap) = & self . snapshot {
123+ if Arc :: ptr_eq ( & snap. inner , & snapshot. inner ) {
124+ // If the snapshot is already the current one, no need to restore
125+ return Ok ( ( ) ) ;
126+ }
127+ }
128+
116129 if self . id != snapshot. inner . sandbox_id ( ) {
117130 return Err ( SnapshotSandboxMismatch ) ;
118131 }
@@ -153,10 +166,7 @@ impl MultiUseSandbox {
153166 func_name : & str ,
154167 args : impl ParameterTuple ,
155168 ) -> Result < Output > {
156- let snapshot = match & self . snapshot {
157- Some ( snapshot) => snapshot. clone ( ) ,
158- None => self . snapshot ( ) ?,
159- } ;
169+ let snapshot = self . snapshot ( ) ?;
160170 let res = self . run ( func_name, args) ;
161171 self . restore ( & snapshot) ?;
162172 res
@@ -208,6 +218,8 @@ impl MultiUseSandbox {
208218 // writes can be rolled back when necessary.
209219 log_then_return ! ( "TODO: Writable mappings not yet supported" ) ;
210220 }
221+ // Reset snapshot since we are mutating the sandbox state
222+ self . snapshot = None ;
211223 unsafe { self . vm . map_region ( rgn) } ?;
212224 self . mem_mgr . unwrap_mgr_mut ( ) . mapped_rgns += 1 ;
213225 Ok ( ( ) )
0 commit comments