@@ -67,6 +67,8 @@ pub struct MultiUseSandbox {
67
67
dispatch_ptr : RawPtr ,
68
68
#[ cfg( gdb) ]
69
69
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.
70
72
snapshot : Option < Snapshot > ,
71
73
}
72
74
@@ -99,20 +101,31 @@ impl MultiUseSandbox {
99
101
/// Create a snapshot of the current state of the sandbox's memory.
100
102
#[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) ) ]
101
103
pub fn snapshot ( & mut self ) -> Result < Snapshot > {
104
+ if let Some ( snapshot) = & self . snapshot {
105
+ return Ok ( snapshot. clone ( ) ) ;
106
+ }
102
107
let mapped_regions_iter = self . vm . get_mapped_regions ( ) ;
103
108
let mapped_regions_vec: Vec < MemoryRegion > = mapped_regions_iter. cloned ( ) . collect ( ) ;
104
109
let memory_snapshot = self
105
110
. mem_mgr
106
111
. unwrap_mgr_mut ( )
107
112
. 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)
111
117
}
112
118
113
119
/// Restore the sandbox's memory to the state captured in the given snapshot.
114
120
#[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) ) ]
115
121
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
+
116
129
if self . id != snapshot. inner . sandbox_id ( ) {
117
130
return Err ( SnapshotSandboxMismatch ) ;
118
131
}
@@ -153,10 +166,7 @@ impl MultiUseSandbox {
153
166
func_name : & str ,
154
167
args : impl ParameterTuple ,
155
168
) -> Result < Output > {
156
- let snapshot = match & self . snapshot {
157
- Some ( snapshot) => snapshot. clone ( ) ,
158
- None => self . snapshot ( ) ?,
159
- } ;
169
+ let snapshot = self . snapshot ( ) ?;
160
170
let res = self . run ( func_name, args) ;
161
171
self . restore ( & snapshot) ?;
162
172
res
@@ -208,6 +218,8 @@ impl MultiUseSandbox {
208
218
// writes can be rolled back when necessary.
209
219
log_then_return ! ( "TODO: Writable mappings not yet supported" ) ;
210
220
}
221
+ // Reset snapshot since we are mutating the sandbox state
222
+ self . snapshot = None ;
211
223
unsafe { self . vm . map_region ( rgn) } ?;
212
224
self . mem_mgr . unwrap_mgr_mut ( ) . mapped_rgns += 1 ;
213
225
Ok ( ( ) )
0 commit comments