pub fn count_open_fds() -> Option<u64> {
#[cfg(target_os = "linux")]
let dir_path = "/proc/self/fd";
#[cfg(not(target_os = "linux"))]
let dir_path = "/dev/fd";
let count = std::fs::read_dir(dir_path)
.ok()?
.filter_map(|entry| entry.ok())
.filter(|e| {
let name = e.file_name();
let s = name.to_string_lossy();
s != "." && s != ".."
})
.count();
Some(count.saturating_sub(1) as u64)
}
pub fn fd_soft_limit() -> Option<u64> {
#[cfg(unix)]
{
let mut rlim = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
let ret = unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) };
if ret == 0 {
#[allow(clippy::unnecessary_cast)]
let cur = rlim.rlim_cur as u64;
#[allow(clippy::unnecessary_cast)]
let infinity = libc::RLIM_INFINITY as u64;
if cur == infinity {
None } else {
Some(cur)
}
} else {
None
}
}
#[cfg(not(unix))]
{
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fd_metrics_returns_sane_values() {
#[cfg(unix)]
{
let fds = count_open_fds();
assert!(
fds.is_some(),
"count_open_fds() must return Some on Unix (got None)"
);
assert!(
fds.unwrap() > 0,
"count_open_fds() must be > 0 (at minimum stdin/stdout/stderr are open)"
);
let limit = fd_soft_limit();
assert!(
limit.is_some(),
"fd_soft_limit() must return Some on Unix (getrlimit RLIMIT_NOFILE failed)"
);
assert!(limit.unwrap() > 0, "fd_soft_limit() must be > 0");
}
}
}