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

Commit 6b7906d

Browse files
authored
libfuzzer fuzzing task perf improvements (#941)
- resuse the regex to parse the output of libfuzzer - added a cancellation notification to report_fuzzer_sys_info. ~~The code seems to be actively waiting this function and consuming some cpu time~~ The notification allows us to reduce the time waiting for the fuzzing loop to terminate. ## Summary of the Pull Request _What is this about?_ ## PR Checklist * [ ] Applies to work item: #xxx * [ ] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/onefuzz) and sign the CLI. * [ ] Tests added/passed * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Info on Pull Request _What does this include?_ ## Validation Steps Performed _How does someone test & validate?_
1 parent 2c72bd5 commit 6b7906d

File tree

2 files changed

+32
-13
lines changed

2 files changed

+32
-13
lines changed

src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ use onefuzz_telemetry::{
1717
EventData,
1818
};
1919
use serde::Deserialize;
20-
use std::{collections::HashMap, path::PathBuf};
20+
use std::{collections::HashMap, path::PathBuf, sync::Arc};
2121
use tempfile::{tempdir_in, TempDir};
2222
use tokio::{
2323
io::{AsyncBufReadExt, BufReader},
24-
sync::mpsc,
24+
select,
25+
sync::{mpsc, Notify},
2526
task,
2627
time::{sleep, Duration},
2728
};
@@ -212,11 +213,12 @@ impl LibFuzzerFuzzTask {
212213
);
213214
let mut running = fuzzer.fuzz(crash_dir.path(), local_inputs, &inputs)?;
214215
let running_id = running.id();
215-
216+
let notify = Arc::new(Notify::new());
216217
let sys_info = task::spawn(report_fuzzer_sys_info(
217218
worker_id,
218219
run_id,
219220
running_id.unwrap_or_default(),
221+
notify.clone(),
220222
));
221223

222224
// Splitting borrow.
@@ -227,7 +229,6 @@ impl LibFuzzerFuzzTask {
227229
let mut stderr = BufReader::new(stderr);
228230

229231
let mut libfuzzer_output: ArrayDeque<[_; LOGS_BUFFER_SIZE], Wrapping> = ArrayDeque::new();
230-
231232
loop {
232233
let mut buf = vec![];
233234
let bytes_read = stderr.read_until(b'\n', &mut buf).await?;
@@ -243,7 +244,10 @@ impl LibFuzzerFuzzTask {
243244
libfuzzer_output.push_back(line);
244245
}
245246

246-
let (exit_status, _) = tokio::join!(running.wait(), sys_info);
247+
let exit_status = running.wait().await;
248+
notify.notify_one();
249+
let _ = sys_info.await;
250+
247251
let exit_status: ExitStatus = exit_status?.into();
248252

249253
let files = list_files(crash_dir.path()).await?;
@@ -323,11 +327,23 @@ fn try_report_iter_update(
323327
Ok(())
324328
}
325329

326-
async fn report_fuzzer_sys_info(worker_id: usize, run_id: Uuid, fuzzer_pid: u32) -> Result<()> {
330+
async fn report_fuzzer_sys_info(
331+
worker_id: usize,
332+
run_id: Uuid,
333+
fuzzer_pid: u32,
334+
cancellation: Arc<Notify>,
335+
) -> Result<()> {
327336
// Allow for sampling CPU usage.
328-
sleep(PROC_INFO_COLLECTION_DELAY).await;
329-
337+
let mut period = tokio::time::interval_at(
338+
tokio::time::Instant::now() + PROC_INFO_COLLECTION_DELAY,
339+
PROC_INFO_PERIOD,
340+
);
330341
loop {
342+
select! {
343+
() = cancellation.notified() => break,
344+
_ = period.tick() => (),
345+
}
346+
331347
// process doesn't exist
332348
if !system::refresh_process(fuzzer_pid)? {
333349
break;
@@ -348,8 +364,6 @@ async fn report_fuzzer_sys_info(worker_id: usize, run_id: Uuid, fuzzer_pid: u32)
348364
// The process no longer exists.
349365
break;
350366
}
351-
352-
sleep(PROC_INFO_PERIOD).await;
353367
}
354368

355369
Ok(())

src/agent/onefuzz/src/libfuzzer.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ use tokio::process::{Child, Command};
2121

2222
const DEFAULT_MAX_TOTAL_SECONDS: i32 = 10 * 60;
2323

24+
use lazy_static::lazy_static;
25+
26+
lazy_static! {
27+
static ref LIBFUZZERLINEREGEX: regex::Regex =
28+
regex::Regex::new(r"#(\d+)\s*(?:pulse|INITED|NEW|REDUCE).*exec/s: (\d+)").unwrap();
29+
}
30+
2431
#[derive(Debug)]
2532
pub struct LibFuzzerMergeOutput {
2633
pub added_files_count: i32,
@@ -304,9 +311,7 @@ impl LibFuzzerLine {
304311
}
305312

306313
pub fn parse(line: &str) -> Result<Option<Self>> {
307-
let re = regex::Regex::new(r"#(\d+)\s*(?:pulse|INITED|NEW|REDUCE).*exec/s: (\d+)")?;
308-
309-
let caps = match re.captures(line) {
314+
let caps = match LIBFUZZERLINEREGEX.captures(line) {
310315
Some(caps) => caps,
311316
None => return Ok(None),
312317
};

0 commit comments

Comments
 (0)