Skip to content

Commit 61e89c7

Browse files
committed
modernize error handling
Problem Currently, we do error handling with the `failure` crate which requires that users are aware of `failure` and use it in their library or application. Solution Switch error handling to use the `thiserror` crate which allows us to derive `std::error::Error` for our error type. Result This library's public API now uses `std::error::Error` in the `Result`s. This allows better composition within higher level libraries and applications.
1 parent 32f2808 commit 61e89c7

22 files changed

+267
-187
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ edition = '2018'
1414
[dependencies]
1515
bcc-sys = "0.13.0"
1616
byteorder = "1.3.4"
17-
failure = "0.1.7"
1817
libc = "0.2.68"
1918
regex = "1.3.5"
19+
thiserror = "1.0.19"
2020

2121
[dev-dependencies]
2222
clap = "2.33.0"

examples/biosnoop.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use bcc::core::BPF;
22
use bcc::perf::init_perf_map;
3+
use bcc::BccError;
34
use clap::{App, Arg};
4-
use failure::Error;
55

66
use core::sync::atomic::{AtomicBool, Ordering};
77
use std::ptr;
@@ -24,7 +24,7 @@ struct data_t {
2424
name: [u8; 16],
2525
}
2626

27-
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
27+
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
2828
let matches = App::new("biosnoop")
2929
.about("Trace block I/O")
3030
.arg(

examples/opensnoop.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ extern crate libc;
55

66
use bcc::core::BPF;
77
use bcc::perf::init_perf_map;
8+
use bcc::BccError;
89
use clap::{App, Arg};
9-
use failure::Error;
1010

1111
use core::sync::atomic::{AtomicBool, Ordering};
1212
use std::ptr;
@@ -34,7 +34,7 @@ struct data_t {
3434
fname: [u8; 255], // NAME_MAX
3535
}
3636

37-
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
37+
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
3838
let matches = App::new("opensnoop")
3939
.about("Prints out filename + PID every time a file is opened")
4040
.arg(

examples/runqlat.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bcc::core::BPF;
2+
use bcc::BccError;
23
use clap::{App, Arg};
3-
use failure::Error;
44

55
use core::sync::atomic::{AtomicBool, Ordering};
66
use std::sync::Arc;
@@ -50,7 +50,7 @@ fn attach_events(bpf: &mut BPF) {
5050
}
5151
}
5252

53-
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
53+
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
5454
let matches = App::new("runqlat")
5555
.about("Reports distribution of scheduler latency")
5656
.arg(

examples/softirqs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use bcc::core::BPF;
2+
use bcc::BccError;
23
use clap::{App, Arg};
3-
use failure::Error;
4+
use std::error::Error;
45

56
use core::sync::atomic::{AtomicBool, Ordering};
67
use std::sync::Arc;
@@ -73,7 +74,7 @@ impl fmt::Display for SoftIRQ {
7374
}
7475
}
7576

76-
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
77+
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
7778
let matches = App::new("softirqs")
7879
.about("Reports time spent in IRQ Handlers")
7980
.arg(

examples/strlen.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ extern crate failure;
44
extern crate libc;
55

66
use bcc::core::BPF;
7+
use bcc::BccError;
78
use byteorder::{NativeEndian, ReadBytesExt};
8-
use failure::Error;
99

1010
use core::sync::atomic::{AtomicBool, Ordering};
1111
use std::io::Cursor;
1212
use std::sync::Arc;
1313

14-
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
14+
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
1515
let code = "
1616
#include <uapi/linux/ptrace.h>
1717

examples/tcpretrans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use bcc::core::BPF;
2+
use bcc::BccError;
23
extern crate chrono;
34
use chrono::Utc;
45
use clap::{App, Arg};
5-
use failure::Error;
66

77
use core::sync::atomic::{AtomicBool, Ordering};
88
use std::net::Ipv4Addr;
@@ -38,7 +38,7 @@ struct ipv6_data_t {
3838
type_: u64,
3939
}
4040

41-
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), Error> {
41+
fn do_main(runnable: Arc<AtomicBool>) -> Result<(), BccError> {
4242
let matches = App::new("biosnoop")
4343
.arg(
4444
Arg::with_name("duration")

src/core/kprobe/v0_4_0.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_ENTRY as BPF_PROBE_ENTRY;
22
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_RETURN as BPF_PROBE_RETURN;
33
use bcc_sys::bccapi::*;
4-
use failure::*;
54

65
use crate::core::make_alphanumeric;
76
use crate::types::MutPointer;
7+
use crate::BccError;
88

99
use regex::Regex;
1010

@@ -23,11 +23,9 @@ pub struct Kprobe {
2323
}
2424

2525
impl Kprobe {
26-
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, Error> {
27-
let cname =
28-
CString::new(name).map_err(|_| format_err!("Nul byte in Kprobe name: {}", name))?;
29-
let cfunction = CString::new(function)
30-
.map_err(|_| format_err!("Nul byte in Kprobe function: {}", function))?;
26+
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, BccError> {
27+
let cname = CString::new(name)?;
28+
let cfunction = CString::new(function)?;
3129
let (pid, cpu, group_fd) = (-1, 0, -1);
3230
let ptr = unsafe {
3331
bpf_attach_kprobe(
@@ -43,7 +41,15 @@ impl Kprobe {
4341
)
4442
};
4543
if ptr.is_null() {
46-
Err(format_err!("Failed to attach Kprobe: {}", name))
44+
match attach_type {
45+
BPF_PROBE_ENTRY => Err(BccError::AttachKprobe {
46+
name: name.to_string(),
47+
}),
48+
BPF_PROBE_RETURN => Err(BccError::AttachKretprobe {
49+
name: name.to_string(),
50+
}),
51+
_ => unreachable!(),
52+
}
4753
} else {
4854
Ok(Self {
4955
p: ptr,
@@ -53,19 +59,17 @@ impl Kprobe {
5359
}
5460
}
5561

56-
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, Error> {
62+
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, BccError> {
5763
let name = format!("p_{}", &make_alphanumeric(function));
5864
Kprobe::new(&name, BPF_PROBE_ENTRY, function, code)
59-
.map_err(|_| format_err!("Failed to attach Kprobe: {}", name))
6065
}
6166

62-
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, Error> {
67+
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, BccError> {
6368
let name = format!("r_{}", &make_alphanumeric(function));
6469
Kprobe::new(&name, BPF_PROBE_RETURN, function, code)
65-
.map_err(|_| format_err!("Failed to attach Kretprobe: {}", name))
6670
}
6771

68-
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, Error> {
72+
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, BccError> {
6973
let mut fns: Vec<String> = vec![];
7074

7175
enum Section {
@@ -117,19 +121,18 @@ impl Kprobe {
117121
Section::End => (),
118122
}
119123
// All functions defined as NOKPROBE_SYMBOL() start with the
120-
// prefix _kbl_addr_*, blacklisting them by looking at the name
124+
// prefix _kbl_addr_*, excluding them by looking at the name
121125
// allows to catch also those symbols that are defined in kernel
122126
// modules.
123127
if fname.starts_with("_kbl_addr_") {
124128
continue;
125129
}
126-
// Explicitly blacklist perf-related functions, they are all
127-
// non-attachable.
128-
else if fname.starts_with("__perf") || fname.starts_with("perf_") {
130+
// Exclude perf-related functions, they are all non-attachable.
131+
if fname.starts_with("__perf") || fname.starts_with("perf_") {
129132
continue;
130133
}
131134
// Exclude all gcc 8's extra .cold functions
132-
else if re.is_match(fname) {
135+
if re.is_match(fname) {
133136
continue;
134137
}
135138
if (t == "t" || t == "w") && fname.contains(event_re) {

src/core/kprobe/v0_6_0.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_ENTRY as BPF_PROBE_ENTRY;
22
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_RETURN as BPF_PROBE_RETURN;
33
use bcc_sys::bccapi::*;
4-
use failure::*;
54

65
use crate::core::make_alphanumeric;
6+
use crate::BccError;
77

88
use regex::Regex;
99

@@ -21,11 +21,9 @@ pub struct Kprobe {
2121
}
2222

2323
impl Kprobe {
24-
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, Error> {
25-
let cname =
26-
CString::new(name).map_err(|_| format_err!("Nul byte in Kprobe name: {}", name))?;
27-
let cfunction = CString::new(function)
28-
.map_err(|_| format_err!("Nul byte in Kprobe function: {}", function))?;
24+
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, BccError> {
25+
let cname = CString::new(name)?;
26+
let cfunction = CString::new(function)?;
2927
let ptr = unsafe {
3028
bpf_attach_kprobe(
3129
code.as_raw_fd(),
@@ -36,7 +34,15 @@ impl Kprobe {
3634
)
3735
};
3836
if ptr < 0 {
39-
Err(format_err!("Failed to attach Kprobe: {}", name))
37+
match attach_type {
38+
BPF_PROBE_ENTRY => Err(BccError::AttachKprobe {
39+
name: name.to_string(),
40+
}),
41+
BPF_PROBE_RETURN => Err(BccError::AttachKretprobe {
42+
name: name.to_string(),
43+
}),
44+
_ => unreachable!(),
45+
}
4046
} else {
4147
Ok(Self {
4248
p: ptr,
@@ -46,19 +52,17 @@ impl Kprobe {
4652
}
4753
}
4854

49-
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, Error> {
55+
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, BccError> {
5056
let name = format!("p_{}", &make_alphanumeric(function));
5157
Kprobe::new(&name, BPF_PROBE_ENTRY, function, code)
52-
.map_err(|_| format_err!("Failed to attach Kprobe: {}", name))
5358
}
5459

55-
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, Error> {
60+
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, BccError> {
5661
let name = format!("r_{}", &make_alphanumeric(function));
5762
Kprobe::new(&name, BPF_PROBE_RETURN, function, code)
58-
.map_err(|_| format_err!("Failed to attach Kretprobe: {}", name))
5963
}
6064

61-
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, Error> {
65+
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, BccError> {
6266
let mut fns: Vec<String> = vec![];
6367

6468
enum Section {
@@ -110,19 +114,18 @@ impl Kprobe {
110114
Section::End => (),
111115
}
112116
// All functions defined as NOKPROBE_SYMBOL() start with the
113-
// prefix _kbl_addr_*, blacklisting them by looking at the name
117+
// prefix _kbl_addr_*, excluding them by looking at the name
114118
// allows to catch also those symbols that are defined in kernel
115119
// modules.
116120
if fname.starts_with("_kbl_addr_") {
117121
continue;
118122
}
119-
// Explicitly blacklist perf-related functions, they are all
120-
// non-attachable.
121-
else if fname.starts_with("__perf") || fname.starts_with("perf_") {
123+
// Exclude perf-related functions, they are all non-attachable.
124+
if fname.starts_with("__perf") || fname.starts_with("perf_") {
122125
continue;
123126
}
124127
// Exclude all gcc 8's extra .cold functions
125-
else if re.is_match(fname) {
128+
if re.is_match(fname) {
126129
continue;
127130
}
128131
if (t == "t" || t == "w") && fname.contains(event_re) {

src/core/kprobe/v0_9_0.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_ENTRY as BPF_PROBE_ENTRY;
22
use bcc_sys::bccapi::bpf_probe_attach_type_BPF_PROBE_RETURN as BPF_PROBE_RETURN;
33
use bcc_sys::bccapi::*;
4-
use failure::*;
54

65
use crate::core::make_alphanumeric;
6+
use crate::BccError;
77

88
use regex::Regex;
99

@@ -21,11 +21,9 @@ pub struct Kprobe {
2121
}
2222

2323
impl Kprobe {
24-
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, Error> {
25-
let cname =
26-
CString::new(name).map_err(|_| format_err!("Nul byte in Kprobe name: {}", name))?;
27-
let cfunction = CString::new(function)
28-
.map_err(|_| format_err!("Nul byte in Kprobe function: {}", function))?;
24+
fn new(name: &str, attach_type: u32, function: &str, code: File) -> Result<Self, BccError> {
25+
let cname = CString::new(name)?;
26+
let cfunction = CString::new(function)?;
2927
let ptr = unsafe {
3028
bpf_attach_kprobe(
3129
code.as_raw_fd(),
@@ -37,7 +35,15 @@ impl Kprobe {
3735
)
3836
};
3937
if ptr < 0 {
40-
Err(format_err!("Failed to attach Kprobe: {}", name))
38+
match attach_type {
39+
BPF_PROBE_ENTRY => Err(BccError::AttachKprobe {
40+
name: name.to_string(),
41+
}),
42+
BPF_PROBE_RETURN => Err(BccError::AttachKretprobe {
43+
name: name.to_string(),
44+
}),
45+
_ => unreachable!(),
46+
}
4147
} else {
4248
Ok(Self {
4349
p: ptr,
@@ -47,19 +53,17 @@ impl Kprobe {
4753
}
4854
}
4955

50-
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, Error> {
56+
pub fn attach_kprobe(function: &str, code: File) -> Result<Self, BccError> {
5157
let name = format!("p_{}", &make_alphanumeric(function));
5258
Kprobe::new(&name, BPF_PROBE_ENTRY, function, code)
53-
.map_err(|_| format_err!("Failed to attach Kprobe: {}", name))
5459
}
5560

56-
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, Error> {
61+
pub fn attach_kretprobe(function: &str, code: File) -> Result<Self, BccError> {
5762
let name = format!("r_{}", &make_alphanumeric(function));
5863
Kprobe::new(&name, BPF_PROBE_RETURN, function, code)
59-
.map_err(|_| format_err!("Failed to attach Kretprobe: {}", name))
6064
}
6165

62-
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, Error> {
66+
pub fn get_kprobe_functions(event_re: &str) -> Result<Vec<String>, BccError> {
6367
let mut fns: Vec<String> = vec![];
6468

6569
enum Section {
@@ -111,19 +115,18 @@ impl Kprobe {
111115
Section::End => (),
112116
}
113117
// All functions defined as NOKPROBE_SYMBOL() start with the
114-
// prefix _kbl_addr_*, blacklisting them by looking at the name
118+
// prefix _kbl_addr_*, excluding them by looking at the name
115119
// allows to catch also those symbols that are defined in kernel
116120
// modules.
117121
if fname.starts_with("_kbl_addr_") {
118122
continue;
119123
}
120-
// Explicitly blacklist perf-related functions, they are all
121-
// non-attachable.
122-
else if fname.starts_with("__perf") || fname.starts_with("perf_") {
124+
// Exclude perf-related functions, they are all non-attachable.
125+
if fname.starts_with("__perf") || fname.starts_with("perf_") {
123126
continue;
124127
}
125128
// Exclude all gcc 8's extra .cold functions
126-
else if re.is_match(fname) {
129+
if re.is_match(fname) {
127130
continue;
128131
}
129132
if (t == "t" || t == "w") && fname.contains(event_re) {

0 commit comments

Comments
 (0)