4
4
use std:: collections:: HashMap ;
5
5
use std:: path:: { Path , PathBuf } ;
6
6
use std:: process:: { Command , Stdio } ;
7
+ use std:: sync:: { Arc , Mutex } ;
7
8
use std:: time:: Duration ;
8
9
9
10
use anyhow:: { Context , Result } ;
@@ -160,9 +161,7 @@ where
160
161
}
161
162
162
163
struct TaskContext < ' a > {
163
- // Optional only to enable temporary move into blocking thread.
164
- cache : Option < ModuleCache > ,
165
-
164
+ cache : Arc < Mutex < ModuleCache > > ,
166
165
config : & ' a Config ,
167
166
coverage : CommandBlockCov ,
168
167
filter : CmdFilter ,
@@ -177,7 +176,7 @@ impl<'a> TaskContext<'a> {
177
176
filter : CmdFilter ,
178
177
heartbeat : Option < TaskHeartbeatClient > ,
179
178
) -> Self {
180
- let cache = Some ( cache) ;
179
+ let cache = Arc :: new ( Mutex :: new ( cache) ) ;
181
180
182
181
Self {
183
182
cache,
@@ -230,19 +229,19 @@ impl<'a> TaskContext<'a> {
230
229
}
231
230
232
231
async fn record_impl ( & mut self , input : & Path ) -> Result < CommandBlockCov > {
233
- // Invariant: `self.cache` must be present on method enter and exit.
234
- let cache = self . cache . take ( ) . expect ( "module cache not present" ) ;
235
-
232
+ let cache = Arc :: clone ( & self . cache ) ;
236
233
let filter = self . filter . clone ( ) ;
237
234
let cmd = self . command_for_input ( input) ?;
238
235
let timeout = self . config . timeout ( ) ;
239
- let recorded =
240
- spawn_blocking ( move || record_os_impl ( cmd, timeout, cache, filter) ) . await ??;
241
-
242
- // Maintain invariant.
243
- self . cache = Some ( recorded. cache ) ;
244
-
245
- Ok ( recorded. coverage )
236
+ let coverage = spawn_blocking ( move || {
237
+ let mut cache = cache
238
+ . lock ( )
239
+ . map_err ( |_| format_err ! ( "module cache mutex lock was poisoned" ) ) ?;
240
+ record_os_impl ( cmd, timeout, & mut cache, filter)
241
+ } )
242
+ . await ??;
243
+
244
+ Ok ( coverage)
246
245
}
247
246
248
247
fn command_for_input ( & self , input : & Path ) -> Result < Command > {
@@ -322,40 +321,35 @@ impl<'a> TaskContext<'a> {
322
321
}
323
322
}
324
323
325
- struct Recorded {
326
- pub cache : ModuleCache ,
327
- pub coverage : CommandBlockCov ,
328
- }
329
-
330
324
#[ cfg( target_os = "linux" ) ]
331
325
fn record_os_impl (
332
326
cmd : Command ,
333
327
timeout : Duration ,
334
- mut cache : ModuleCache ,
328
+ cache : & mut ModuleCache ,
335
329
filter : CmdFilter ,
336
- ) -> Result < Recorded > {
330
+ ) -> Result < CommandBlockCov > {
337
331
use coverage:: block:: linux:: Recorder ;
338
332
339
- let coverage = Recorder :: record ( cmd, timeout, & mut cache, filter) ?;
333
+ let coverage = Recorder :: record ( cmd, timeout, cache, filter) ?;
340
334
341
- Ok ( Recorded { cache , coverage } )
335
+ Ok ( coverage)
342
336
}
343
337
344
338
#[ cfg( target_os = "windows" ) ]
345
339
fn record_os_impl (
346
340
cmd : Command ,
347
341
timeout : Duration ,
348
- mut cache : ModuleCache ,
342
+ cache : & mut ModuleCache ,
349
343
filter : CmdFilter ,
350
- ) -> Result < Recorded > {
344
+ ) -> Result < CommandBlockCov > {
351
345
use coverage:: block:: windows:: { Recorder , RecorderEventHandler } ;
352
346
353
- let mut recorder = Recorder :: new ( & mut cache, filter) ;
347
+ let mut recorder = Recorder :: new ( cache, filter) ;
354
348
let mut handler = RecorderEventHandler :: new ( & mut recorder, timeout) ;
355
349
handler. run ( cmd) ?;
356
350
let coverage = recorder. into_coverage ( ) ;
357
351
358
- Ok ( Recorded { cache , coverage } )
352
+ Ok ( coverage)
359
353
}
360
354
361
355
#[ async_trait]
0 commit comments