cgroups_rs/
lib.rs

1// Copyright (c) 2018 Levente Kurusa
2// Copyright (c) 2020-2025 Ant Group
3//
4// SPDX-License-Identifier: Apache-2.0 or MIT
5//
6
7pub mod fs;
8#[cfg(feature = "oci")]
9pub mod manager;
10#[cfg(feature = "oci")]
11pub use manager::{FsManager, Manager, SystemdManager};
12pub mod stats;
13pub use stats::CgroupStats;
14pub mod systemd;
15
16/// The maximum value for CPU shares in cgroups v1
17pub const CPU_SHARES_V1_MAX: u64 = 262144;
18/// The maximum value for CPU weight in cgroups v2
19pub const CPU_WEIGHT_V2_MAX: u64 = 10000;
20
21/// The current state of the control group
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub enum FreezerState {
24    /// The processes in the control group are _not_ frozen.
25    Thawed,
26    /// The processes in the control group are in the processes of being frozen.
27    Freezing,
28    /// The processes in the control group are frozen.
29    Frozen,
30}
31
32/// A structure representing a `pid`. Currently implementations exist for `u64` and
33/// `std::process::Child`.
34#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
35pub struct CgroupPid {
36    /// The process identifier
37    pub pid: u64,
38}
39
40impl From<u64> for CgroupPid {
41    fn from(u: u64) -> CgroupPid {
42        CgroupPid { pid: u }
43    }
44}
45
46impl From<&std::process::Child> for CgroupPid {
47    fn from(u: &std::process::Child) -> CgroupPid {
48        CgroupPid { pid: u.id() as u64 }
49    }
50}
51
52#[cfg(test)]
53pub mod tests {
54    use std::fs;
55    use std::process::{Child, Command, Stdio};
56
57    /// Start a mock subprocess that will sleep forever
58    pub fn spawn_sleep_inf() -> Child {
59        let child = Command::new("sleep")
60            .arg("infinity")
61            .spawn()
62            .expect("Failed to start mock subprocess");
63        child
64    }
65
66    pub fn spawn_yes() -> Child {
67        let devnull = fs::File::create("/dev/null").expect("cannot open /dev/null");
68        let child = Command::new("yes")
69            .stdout(Stdio::from(devnull))
70            .spawn()
71            .expect("Failed to start mock subprocess");
72        child
73    }
74
75    pub fn systemd_version() -> Option<usize> {
76        let output = Command::new("systemd").arg("--version").output().ok()?; // Return None if command execution fails
77
78        if !output.status.success() {
79            return None;
80        }
81
82        let stdout = String::from_utf8_lossy(&output.stdout);
83
84        // The first line is typically like "systemd 254 (254.5-1-arch)"
85        let first_line = stdout.lines().next()?;
86        let mut words = first_line.split_whitespace();
87
88        words.next()?; // Skip the "systemd" word
89        let version_str = words.next()?; // The version number as string
90
91        version_str.parse::<usize>().ok()
92    }
93}