Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 80387bd

Browse files
authored
Use sync pointers for writing ModuleCache off-thread (#1033)
1 parent 1908951 commit 80387bd

File tree

1 file changed

+21
-27
lines changed
  • src/agent/onefuzz-agent/src/tasks/coverage

1 file changed

+21
-27
lines changed

src/agent/onefuzz-agent/src/tasks/coverage/generic.rs

+21-27
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use std::collections::HashMap;
55
use std::path::{Path, PathBuf};
66
use std::process::{Command, Stdio};
7+
use std::sync::{Arc, Mutex};
78
use std::time::Duration;
89

910
use anyhow::{Context, Result};
@@ -160,9 +161,7 @@ where
160161
}
161162

162163
struct TaskContext<'a> {
163-
// Optional only to enable temporary move into blocking thread.
164-
cache: Option<ModuleCache>,
165-
164+
cache: Arc<Mutex<ModuleCache>>,
166165
config: &'a Config,
167166
coverage: CommandBlockCov,
168167
filter: CmdFilter,
@@ -177,7 +176,7 @@ impl<'a> TaskContext<'a> {
177176
filter: CmdFilter,
178177
heartbeat: Option<TaskHeartbeatClient>,
179178
) -> Self {
180-
let cache = Some(cache);
179+
let cache = Arc::new(Mutex::new(cache));
181180

182181
Self {
183182
cache,
@@ -230,19 +229,19 @@ impl<'a> TaskContext<'a> {
230229
}
231230

232231
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);
236233
let filter = self.filter.clone();
237234
let cmd = self.command_for_input(input)?;
238235
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)
246245
}
247246

248247
fn command_for_input(&self, input: &Path) -> Result<Command> {
@@ -322,40 +321,35 @@ impl<'a> TaskContext<'a> {
322321
}
323322
}
324323

325-
struct Recorded {
326-
pub cache: ModuleCache,
327-
pub coverage: CommandBlockCov,
328-
}
329-
330324
#[cfg(target_os = "linux")]
331325
fn record_os_impl(
332326
cmd: Command,
333327
timeout: Duration,
334-
mut cache: ModuleCache,
328+
cache: &mut ModuleCache,
335329
filter: CmdFilter,
336-
) -> Result<Recorded> {
330+
) -> Result<CommandBlockCov> {
337331
use coverage::block::linux::Recorder;
338332

339-
let coverage = Recorder::record(cmd, timeout, &mut cache, filter)?;
333+
let coverage = Recorder::record(cmd, timeout, cache, filter)?;
340334

341-
Ok(Recorded { cache, coverage })
335+
Ok(coverage)
342336
}
343337

344338
#[cfg(target_os = "windows")]
345339
fn record_os_impl(
346340
cmd: Command,
347341
timeout: Duration,
348-
mut cache: ModuleCache,
342+
cache: &mut ModuleCache,
349343
filter: CmdFilter,
350-
) -> Result<Recorded> {
344+
) -> Result<CommandBlockCov> {
351345
use coverage::block::windows::{Recorder, RecorderEventHandler};
352346

353-
let mut recorder = Recorder::new(&mut cache, filter);
347+
let mut recorder = Recorder::new(cache, filter);
354348
let mut handler = RecorderEventHandler::new(&mut recorder, timeout);
355349
handler.run(cmd)?;
356350
let coverage = recorder.into_coverage();
357351

358-
Ok(Recorded { cache, coverage })
352+
Ok(coverage)
359353
}
360354

361355
#[async_trait]

0 commit comments

Comments
 (0)