Skip to content

Commit f906237

Browse files
committed
examples/rust: Fix improper error handling
The error handling in the profile example is insufficient. Specifically, we never check for the success of perf_event_open. If it fails, we end up passing an FD of -1 to libbpf's bpf_program__attach_perf_event_opts, which in turns barks at us. Make sure to properly check for errors. Also address clippy issues and improper formatting along the way. Signed-off-by: Daniel Müller <[email protected]>
1 parent 7ec721a commit f906237

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

examples/rust/profile/src/main.rs

+23-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::io::Error;
1+
use std::io;
22
use std::mem;
33
use std::time::Duration;
44

@@ -9,6 +9,7 @@ use clap::Parser;
99

1010
use libbpf_rs::skel::OpenSkel as _;
1111
use libbpf_rs::skel::SkelBuilder as _;
12+
use libbpf_rs::ErrorExt as _;
1213

1314
use nix::unistd::close;
1415

@@ -40,7 +41,7 @@ struct stacktrace_event {
4041
ustack: [u64; MAX_STACK_DEPTH],
4142
}
4243

43-
fn init_perf_monitor(freq: u64) -> Vec<i32> {
44+
fn init_perf_monitor(freq: u64) -> Result<Vec<i32>, libbpf_rs::Error> {
4445
let nprocs = libbpf_rs::num_possible_cpus().unwrap();
4546
let pid = -1;
4647
let buf: Vec<u8> = vec![0; mem::size_of::<syscall::perf_event_attr>()];
@@ -56,8 +57,13 @@ fn init_perf_monitor(freq: u64) -> Vec<i32> {
5657
attr.flags = 1 << 10; // freq = 1
5758
(0..nprocs)
5859
.map(|cpu| {
59-
let fd = syscall::perf_event_open(attr.as_ref(), pid, cpu as i32, -1, 0);
60-
fd as i32
60+
let fd = syscall::perf_event_open(attr.as_ref(), pid, cpu as i32, -1, 0) as i32;
61+
if fd == -1 {
62+
Err(libbpf_rs::Error::from(io::Error::last_os_error()))
63+
.context("failed to open perf event")
64+
} else {
65+
Ok(fd)
66+
}
6167
})
6268
.collect()
6369
}
@@ -72,7 +78,11 @@ fn attach_perf_event(
7278
.collect()
7379
}
7480

75-
fn print_frame(name: &str, addr_info: Option<(blazesym::Addr, blazesym::Addr, usize)>, code_info: &Option<symbolize::CodeInfo>) {
81+
fn print_frame(
82+
name: &str,
83+
addr_info: Option<(blazesym::Addr, blazesym::Addr, usize)>,
84+
code_info: &Option<symbolize::CodeInfo>,
85+
) {
7686
let code_info = code_info.as_ref().map(|code_info| {
7787
let path = code_info.to_path();
7888
let path = path.display();
@@ -175,9 +185,7 @@ fn event_handler(symbolizer: &symbolize::Symbolizer, data: &[u8]) -> ::std::os::
175185
return 1;
176186
}
177187

178-
let comm = std::str::from_utf8(&event.comm)
179-
.or::<Error>(Ok("<unknown>"))
180-
.unwrap();
188+
let comm = std::str::from_utf8(&event.comm).unwrap_or("<unknown>");
181189
println!("COMM: {} (pid={}) @ CPU {}", comm, event.pid, event.cpu_id);
182190

183191
if event.kstack_size > 0 {
@@ -216,7 +224,7 @@ struct Args {
216224
verbosity: u8,
217225
}
218226

219-
fn main() -> Result<(), Error> {
227+
fn main() -> Result<(), libbpf_rs::Error> {
220228
let args = Args::parse();
221229
let level = match args.verbosity {
222230
0 => LevelFilter::WARN,
@@ -240,21 +248,22 @@ fn main() -> Result<(), Error> {
240248
let open_skel = skel_builder.open().unwrap();
241249
let mut skel = open_skel.load().unwrap();
242250

243-
let pefds = init_perf_monitor(freq);
251+
let pefds = init_perf_monitor(freq)?;
244252
let _links = attach_perf_event(&pefds, skel.progs_mut().profile());
245253

246254
let maps = skel.maps();
247255
let mut builder = libbpf_rs::RingBufferBuilder::new();
248256
builder
249-
.add(maps.events(), move |data| {
250-
event_handler(&symbolizer, data)
251-
})
257+
.add(maps.events(), move |data| event_handler(&symbolizer, data))
252258
.unwrap();
253259
let ringbuf = builder.build().unwrap();
254260
while ringbuf.poll(Duration::MAX).is_ok() {}
255261

256262
for pefd in pefds {
257-
close(pefd)?;
263+
close(pefd)
264+
.map_err(io::Error::from)
265+
.map_err(libbpf_rs::Error::from)
266+
.context("failed to close perf event")?;
258267
}
259268

260269
Ok(())

0 commit comments

Comments
 (0)