-
-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OpenBSD support #59
Changes from all commits
2908639
2c5a6b4
a29067d
3512bc3
da32542
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
use std::convert::TryInto as _; | ||
|
||
use super::Metrics; | ||
|
||
fn getrusage(who: libc::c_int) -> Option<libc::rusage> { | ||
let mut usage = std::mem::MaybeUninit::zeroed(); | ||
// SAFETY: libc call; usage is valid pointer to rusage struct | ||
if unsafe { libc::getrusage(who, usage.as_mut_ptr()) } == 0 { | ||
// SAFETY: libc call was success, struct must be initialized | ||
Some(unsafe { usage.assume_init() }) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn getrlimit(resource: libc::c_int) -> Option<libc::rlimit> { | ||
let mut limit = std::mem::MaybeUninit::zeroed(); | ||
// SAFETY: libc call; limit is valid pointer to rlimit struct | ||
if unsafe { libc::getrlimit(resource, limit.as_mut_ptr()) } == 0 { | ||
// SAFETY: libc call was success, struct must be initialized | ||
Some(unsafe { limit.assume_init() }) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
fn translate_rlim(rlim: libc::rlim_t) -> u64 { | ||
if rlim == libc::RLIM_INFINITY { | ||
0 | ||
} else { | ||
rlim as u64 | ||
} | ||
} | ||
|
||
fn kinfo_getproc(pid: libc::pid_t) -> Option<libc::kinfo_proc> { | ||
let mut kinfo_proc = std::mem::MaybeUninit::zeroed(); | ||
let kinfo_proc_size = std::mem::size_of_val(&kinfo_proc) as libc::size_t; | ||
let mut data_size = kinfo_proc_size; | ||
|
||
// code from deno doing similar stuff: https://github.com/denoland/deno/blob/20ae8db50d7d48ad020b83ebe78dc0e9e9eab3b2/runtime/ops/os/mod.rs#L415 | ||
let mib = [ | ||
libc::CTL_KERN, | ||
libc::KERN_PROC, | ||
libc::KERN_PROC_PID, | ||
pid, | ||
// this is required because MIB is array of ints, and is safe | ||
// as long size of kinfo_proc structure doesn't exceed 2GB | ||
kinfo_proc_size.try_into().unwrap(), | ||
1, | ||
]; | ||
|
||
Comment on lines
+46
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle potential failure in At line 48, Apply this diff to gracefully handle conversion errors: let mib = [
libc::CTL_KERN,
libc::KERN_PROC,
libc::KERN_PROC_PID,
pid,
- kinfo_proc_size.try_into().unwrap(),
+ match kinfo_proc_size.try_into() {
+ Ok(size) => size,
+ Err(_) => return None, // Handle the error appropriately
+ },
1,
]; Alternatively, if you're confident the size will always fit, consider using kinfo_proc_size.try_into().expect("kinfo_proc_size exceeds libc::c_int range"),
|
||
// SAFETY: libc call; mib is statically initialized, kinfo_proc is valid pointer | ||
// to kinfo_proc and data_size holds its size | ||
if unsafe { | ||
libc::sysctl( | ||
mib.as_ptr(), | ||
mib.len() as _, | ||
kinfo_proc.as_mut_ptr() as *mut libc::c_void, | ||
&mut data_size, | ||
std::ptr::null_mut(), | ||
0, | ||
) | ||
} == 0 | ||
&& data_size == kinfo_proc_size | ||
{ | ||
// SAFETY: libc call was success and check for struct size passed, struct must be initialized | ||
Some(unsafe { kinfo_proc.assume_init() }) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub fn collect() -> Metrics { | ||
let mut metrics = Metrics::default(); | ||
|
||
// TODO: this is based on freebsd.rs, but lacks | ||
// - virtual_memory_bytes (kinfo_proc::p_vm_map_size contains zero) | ||
// - virtual_memory_max_bytes (openbsd lacks RLIMIT_AS) | ||
// - threads (no corresponding field in kinfo_proc( | ||
// - open_fds (no idea where to get it from) | ||
|
||
if let Some(usage) = getrusage(libc::RUSAGE_SELF) { | ||
metrics.cpu_seconds_total = Some( | ||
(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) as f64 | ||
+ (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec) as f64 / 1000000.0, | ||
); | ||
} | ||
|
||
if let Some(limit_as) = getrlimit(libc::RLIMIT_NOFILE) { | ||
metrics.max_fds = Some(translate_rlim(limit_as.rlim_cur)); | ||
} | ||
|
||
// SAFETY: libc call | ||
let pid = unsafe { libc::getpid() }; | ||
|
||
if let Some(kinfo_proc) = kinfo_getproc(pid) { | ||
// reference: | ||
// https://github.com/openbsd/src/blob/782feb691bc15d1abd5f5c66fe3c0d336903a461/sys/sys/sysctl.h#L370 | ||
|
||
// SAFETY: libc call | ||
let pagesize = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as u64; | ||
metrics.resident_memory_bytes = Some(kinfo_proc.p_vm_rssize as u64 * pagesize); | ||
metrics.start_time_seconds = Some(kinfo_proc.p_ustart_sec); | ||
} | ||
|
||
metrics | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review handling of
RLIM_INFINITY
intranslate_rlim
functionIn the
translate_rlim
function, mappingRLIM_INFINITY
to0
might be misleading, as0
could be interpreted as no resource limit rather than an infinite limit. Consider usingu64::MAX
or a sentinel value that more clearly represents an infinite limit.Apply this diff to adjust the handling:
📝 Committable suggestion