Skip to content
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

Remove lazy-static dependency #308

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion procfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ serde1 = ["serde", "procfs-core/serde1"]
procfs-core = { path = "../procfs-core", version = "0.16.0-RC1", default-features = false }
rustix = { version = "0.38.19", features = ["fs", "process", "param", "system", "thread"] }
bitflags = { version = "2.0", default-features = false }
lazy_static = "1.0.2"
chrono = {version = "0.4.20", optional = true, features = ["clock"], default-features = false }
hex = "0.4"
flate2 = { version = "1.0.3", optional = true }
Expand Down
27 changes: 1 addition & 26 deletions procfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
pub use procfs_core::*;

use bitflags::bitflags;
use lazy_static::lazy_static;

use rustix::fd::AsFd;
use std::collections::HashMap;
Expand Down Expand Up @@ -202,28 +201,6 @@ pub use crate::sys::kernel::BuildInfo as KernelBuildInfo;
pub use crate::sys::kernel::Type as KernelType;
pub use crate::sys::kernel::Version as KernelVersion;

lazy_static! {
/// The number of clock ticks per second.
///
/// This is calculated from `sysconf(_SC_CLK_TCK)`.
static ref TICKS_PER_SECOND: u64 = {
ticks_per_second()
};
/// The version of the currently running kernel.
///
/// This is a lazily constructed static. You can also get this information via
/// [KernelVersion::new()].
static ref KERNEL: ProcResult<KernelVersion> = {
KernelVersion::current()
};
/// Memory page size, in bytes.
///
/// This is calculated from `sysconf(_SC_PAGESIZE)`.
static ref PAGESIZE: u64 = {
page_size()
};
}

/// A wrapper around a `File` that remembers the name of the path
struct FileWrapper {
inner: File,
Expand Down Expand Up @@ -524,9 +501,7 @@ mod tests {

#[test]
fn test_statics() {
println!("{:?}", *TICKS_PER_SECOND);
println!("{:?}", *KERNEL);
println!("{:?}", *PAGESIZE);
println!("{:?}", crate::sys::kernel::Version::cached());
}

#[test]
Expand Down
5 changes: 3 additions & 2 deletions procfs/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

use super::*;
use crate::net::{TcpNetEntry, UdpNetEntry};
use crate::sys::kernel::Version;

pub use procfs_core::process::*;
use rustix::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
Expand Down Expand Up @@ -154,7 +155,7 @@ impl FDInfo {
let p = path.as_ref();
let root = base.as_ref().join(p);
// for 2.6.39 <= kernel < 3.6 fstat doesn't support O_PATH see https://github.com/eminence/procfs/issues/265
let flags = match *crate::KERNEL {
let flags = match Version::cached() {
Ok(v) if v < KernelVersion::new(3, 6, 0) => OFlags::NOFOLLOW | OFlags::CLOEXEC,
Ok(_) => OFlags::NOFOLLOW | OFlags::PATH | OFlags::CLOEXEC,
Err(_) => OFlags::NOFOLLOW | OFlags::PATH | OFlags::CLOEXEC,
Expand Down Expand Up @@ -224,7 +225,7 @@ impl Process {
/// Returns a `Process` based on a specified `/proc/<pid>` path.
pub fn new_with_root(root: PathBuf) -> ProcResult<Process> {
// for 2.6.39 <= kernel < 3.6 fstat doesn't support O_PATH see https://github.com/eminence/procfs/issues/265
let flags = match *crate::KERNEL {
let flags = match Version::cached() {
Ok(v) if v < KernelVersion::new(3, 6, 0) => OFlags::DIRECTORY | OFlags::CLOEXEC,
Ok(_) => OFlags::PATH | OFlags::DIRECTORY | OFlags::CLOEXEC,
Err(_) => OFlags::PATH | OFlags::DIRECTORY | OFlags::CLOEXEC,
Expand Down
40 changes: 38 additions & 2 deletions procfs/src/sys/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
use std::cmp;
use std::collections::HashSet;
use std::str::FromStr;
use std::sync::atomic::{AtomicU32, Ordering};

use bitflags::bitflags;

use crate::{read_value, write_value, ProcError, ProcResult, KERNEL};
use crate::{read_value, write_value, ProcError, ProcResult};

pub mod keys;
pub mod random;
Expand All @@ -34,6 +35,41 @@ impl Version {
read_value("/proc/sys/kernel/osrelease")
}

/// Cached version of the kernel version.
pub(crate) fn cached() -> ProcResult<Self> {
const SENTINEL: u32 = 0;
static KERNEL: AtomicU32 = AtomicU32::new(SENTINEL);

// Try to load the kernel version.
let mut kernel = KERNEL.load(Ordering::Relaxed);

// If we haven't loaded the kernel version yet, try to here.
if kernel == SENTINEL {
kernel = Self::current()?.to_u32();

// Try to store it in the cache.
KERNEL.store(kernel, Ordering::Release);
}

Ok(Self::from_u32(kernel))
}

/// Convert kernel version to an arbitrary `u32` value.
fn to_u32(self) -> u32 {
let [lo, hi] = u16::to_ne_bytes(self.patch);
u32::from_ne_bytes([self.major, self.minor, lo, hi])
}

/// Convert kernel version from an arbitrary `u32` value.
fn from_u32(val: u32) -> Self {
let [major, minor, lo, hi] = u32::to_ne_bytes(val);
Self {
major,
minor,
patch: u16::from_ne_bytes([lo, hi])
}
}

/// Parses a kernel version string, in major.minor.release syntax.
///
/// Note that any extra information (stuff after a dash) is ignored.
Expand Down Expand Up @@ -447,7 +483,7 @@ pub fn threads_max() -> ProcResult<u32> {
/// Since Linux 4.1, this value is bounded, and must be in the range [THREADS_MIN]..=[THREADS_MAX].
/// This function will return an error if that is not the case.
pub fn set_threads_max(new_limit: u32) -> ProcResult<()> {
if let Ok(kernel) = *KERNEL {
if let Ok(kernel) = Version::cached() {
if kernel.major >= 4 && kernel.minor >= 1 && !(THREADS_MIN..=THREADS_MAX).contains(&new_limit) {
return Err(ProcError::Other(format!(
"{} is outside the THREADS_MIN..=THREADS_MAX range",
Expand Down
20 changes: 9 additions & 11 deletions procfs/src/sys/kernel/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
//! Note that some of these entries are only documented in random(4), while some are also documented under proc(5)

use crate::{read_value, write_value, ProcError, ProcResult};
use lazy_static::lazy_static;
use std::path::Path;

lazy_static! {
static ref RANDOM_ROOT: std::path::PathBuf = std::path::PathBuf::from("/proc/sys/kernel/random");
}
const RANDOM_ROOT: &str = "/proc/sys/kernel/random";

/// This read-only file gives the available entropy, in bits. This will be a number in the range
/// 0 to 4096
pub fn entropy_avail() -> ProcResult<u16> {
read_value(RANDOM_ROOT.join("entropy_avail"))
read_value(Path::new(RANDOM_ROOT).join("entropy_avail"))
}

/// This file gives the size of the entropy pool
Expand All @@ -22,7 +20,7 @@ pub fn entropy_avail() -> ProcResult<u16> {
///
/// See `man random(4)` for more information
pub fn poolsize() -> ProcResult<u16> {
read_value(RANDOM_ROOT.join("poolsize"))
read_value(Path::new(RANDOM_ROOT).join("poolsize"))
}

/// This file contains the number of bits of entropy required for waking up processes that sleep waiting
Expand All @@ -33,10 +31,10 @@ pub fn poolsize() -> ProcResult<u16> {
/// This will first attempt to read from `/proc/sys/kernel/random/read_wakeup_threshold` but it
/// will fallback to `/proc/sys/kernel/random/write_wakeup_threshold` if the former file is not found.
pub fn read_wakeup_threshold() -> ProcResult<u32> {
match read_value(RANDOM_ROOT.join("read_wakeup_threshold")) {
match read_value(Path::new(RANDOM_ROOT).join("read_wakeup_threshold")) {
Ok(val) => Ok(val),
Err(err) => match err {
ProcError::NotFound(_) => read_value(RANDOM_ROOT.join("write_wakeup_threshold")),
ProcError::NotFound(_) => read_value(Path::new(RANDOM_ROOT).join("write_wakeup_threshold")),
err => Err(err),
},
}
Expand All @@ -45,17 +43,17 @@ pub fn read_wakeup_threshold() -> ProcResult<u32> {
/// This file contains the number of bits of entropy below which we wake up processes that do a
/// select(2) or poll(2) for write access to /dev/random. These values can be changed by writing to the file.
pub fn write_wakeup_threshold(new_value: u32) -> ProcResult<()> {
write_value(RANDOM_ROOT.join("write_wakeup_threshold"), new_value)
write_value(Path::new(RANDOM_ROOT).join("write_wakeup_threshold"), new_value)
}

/// This read-only file randomly generates a fresh 128-bit UUID on each read
pub fn uuid() -> ProcResult<String> {
read_value(RANDOM_ROOT.join("uuid"))
read_value(Path::new(RANDOM_ROOT).join("uuid"))
}

/// This is a read-only file containing a 128-bit UUID generated at boot
pub fn boot_id() -> ProcResult<String> {
read_value(RANDOM_ROOT.join("boot_id"))
read_value(Path::new(RANDOM_ROOT).join("boot_id"))
}

#[cfg(test)]
Expand Down
Loading