Skip to content

Commit

Permalink
fix: panic when perf counter could not be initialized (#16)
Browse files Browse the repository at this point in the history
As reported in #14, the CPU CPI sampler will panic if the cycles or
instructions perf counters cannot be initialized.

This PR fixes the bug by returning a Nop sampler if there are
exceptions during initialization.
  • Loading branch information
brayniac authored May 9, 2023
1 parent 1e9bcaa commit ddc1390
Showing 1 changed file with 55 additions and 26 deletions.
81 changes: 55 additions & 26 deletions src/samplers/cpu/cpi/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use super::stats::*;
use super::*;
use crate::common::Counter;
use crate::common::{Counter, Nop};
use perf_event::events::Hardware;
use perf_event::{Builder, Group};

#[distributed_slice(CPU_SAMPLERS)]
fn init(config: &Config) -> Box<dyn Sampler> {
Box::new(Cpi::new(config))
if let Ok(cpi) = Cpi::new(config) {
Box::new(cpi)
} else {
Box::new(Nop {})
}
}

pub struct Cpi {
Expand All @@ -18,37 +22,62 @@ pub struct Cpi {
}

impl Cpi {
pub fn new(_config: &Config) -> Self {
pub fn new(_config: &Config) -> Result<Self, ()> {
let now = Instant::now();

let mut group = Group::new().expect("couldn't init perf group");
let counters = vec![
(
Counter::new(&CPU_CYCLES, None),
Builder::new()
.group(&mut group)
.kind(Hardware::CPU_CYCLES)
.build()
.expect("failed to init cycles counter"),
),
(
Counter::new(&CPU_INSTRUCTIONS, None),
Builder::new()
.group(&mut group)
.kind(Hardware::INSTRUCTIONS)
.build()
.expect("failed to init instructions counter"),
),
];
group.enable().expect("couldn't enable perf counters");

Self {
// initialize a group for the perf counters
let mut group = match Group::new() {
Ok(g) => g,
Err(_) => {
error!("couldn't init perf group");
return Err(());
}
};

// initialize the counters
let mut counters = vec![];

match Builder::new()
.group(&mut group)
.kind(Hardware::CPU_CYCLES)
.build()
{
Ok(counter) => {
counters.push((Counter::new(&CPU_CYCLES, None), counter));
}
Err(_) => {
error!("failed to initialize cpu cycles perf counter");
return Err(());
}
}

match Builder::new()
.group(&mut group)
.kind(Hardware::INSTRUCTIONS)
.build()
{
Ok(counter) => {
counters.push((Counter::new(&CPU_INSTRUCTIONS, None), counter));
}
Err(_) => {
error!("failed to initialize cpu instructions perf counter");
return Err(());
}
}

// enable the counters in the group
if group.enable().is_err() {
error!("couldn't enable perf counter group");
return Err(());
}

Ok(Self {
prev: now,
next: now,
interval: Duration::from_millis(10),
group,
counters,
}
})
}
}

Expand Down

0 comments on commit ddc1390

Please sign in to comment.