pub struct CgroupManager { /* private fields */ }Implementations§
Source§impl CgroupManager
impl CgroupManager
pub fn new() -> Result<Self>
Sourcepub fn at(base_path: PathBuf) -> Self
pub fn at(base_path: PathBuf) -> Self
A manager rooted at base_path, with no checks. For tests and
diagnostics.
Sourcepub fn default_base_path() -> PathBuf
pub fn default_base_path() -> PathBuf
rlm’s base cgroup: user@UID.service/rlm when the user’s systemd
service cgroup exists, else /sys/fs/cgroup/rlm.
Sourcepub fn prepare_cgroup(&self, name: &str, limit: &Limit) -> Result<Prepared>
pub fn prepare_cgroup(&self, name: &str, limit: &Limit) -> Result<Prepared>
Create a cgroup for a process and set limits BEFORE adding the process. If a memory or CPU limit cannot be set, a cgroup this call created is removed again; one that already existed is left alone, so a failed limit write never empties a cgroup that holds processes.
Sourcepub fn placement_command(&self, cgroup_path: &Path, program: &str) -> Command
pub fn placement_command(&self, cgroup_path: &Path, program: &str) -> Command
Build a Command that places the spawned child into cgroup_path
before it execs the target program, so resource limits apply from the
process’s very first instruction.
Without this, a process that allocates aggressively at startup could blow past the limit during the window between spawn and being added to the cgroup — exactly the freeze scenario this tool exists to prevent.
Writing “0” to cgroup.procs from the post-fork, pre-exec child moves it
into the cgroup. The file is opened in the parent so the closure performs
only an async-signal-safe write to an already-open fd (no allocation, no
locks). Placement is best-effort: on failure the process still launches,
so callers should still call add_to_cgroup after
spawn as a fallback. Add command arguments to the returned Command.
Sourcepub fn add_to_cgroup(&self, cgroup_path: &Path, pid: u32) -> Result<()>
pub fn add_to_cgroup(&self, cgroup_path: &Path, pid: u32) -> Result<()>
Add a process to an existing cgroup
Sourcepub fn find_cgroup_for_pid(&self, pid: u32) -> Option<String>
pub fn find_cgroup_for_pid(&self, pid: u32) -> Option<String>
Find if a PID is already in an rlm-managed cgroup. The unlimit
bucket is not a managed cgroup, so released processes can be limited
again.
Sourcepub fn apply_limit(&self, pid: u32, limit: &Limit) -> Result<Vec<String>>
pub fn apply_limit(&self, pid: u32, limit: &Limit) -> Result<Vec<String>>
Apply resource limits to a process (creates cgroup and adds process). Returns non-fatal warnings.
Sourcepub fn apply_limit_to_multiple(
&self,
pids: &[u32],
limit: &Limit,
cgroup_name: &str,
) -> Result<Vec<String>>
pub fn apply_limit_to_multiple( &self, pids: &[u32], limit: &Limit, cgroup_name: &str, ) -> Result<Vec<String>>
Apply resource limits to multiple processes (all share the same limit pool) All processes are added to a single cgroup, so they share the resource limits. For example, if you limit 10 processes to 4GB memory, they share 4GB total, not 4GB each. Returns non-fatal warnings, including PIDs that could not be added.
Sourcepub fn remove_limit(&self, pid: u32) -> Result<()>
pub fn remove_limit(&self, pid: u32) -> Result<()>
Remove limits from a process
Sourcepub fn remove_application_limit(&self, cgroup_name: &str) -> Result<()>
pub fn remove_application_limit(&self, cgroup_name: &str) -> Result<()>
Remove limits from an application cgroup (removes all processes in the cgroup)
Sourcepub fn cleanup_cgroup(&self, name: &str) -> Result<()>
pub fn cleanup_cgroup(&self, name: &str) -> Result<()>
Clean up a cgroup by name (moves processes out and deletes cgroup)
Sourcepub fn is_populated(&self, name: &str) -> Option<bool>
pub fn is_populated(&self, name: &str) -> Option<bool>
Whether the named child cgroup (or a descendant) holds a process, from
its cgroup.events. None if unreadable.
Sourcepub fn oom_kills(&self, name: &str) -> Option<u64>
pub fn oom_kills(&self, name: &str) -> Option<u64>
The oom_kill count from the named cgroup’s memory.events.
Sourcepub fn memory_max(&self, name: &str) -> Option<u64>
pub fn memory_max(&self, name: &str) -> Option<u64>
The named cgroup’s memory.max in bytes; None for max or unreadable.
Sourcepub fn remove_if_empty(&self, name: &str) -> Result<bool>
pub fn remove_if_empty(&self, name: &str) -> Result<bool>
Remove the named cgroup only if it holds no process. Ok(false) when
it is populated; a cgroup that is already gone counts as removed.
Never moves processes.
Sourcepub fn cgroup_exists(&self, name: &str) -> bool
pub fn cgroup_exists(&self, name: &str) -> bool
Whether a child cgroup with this name currently exists.
Sourcepub fn pids_in_cgroup(&self, name: &str) -> Vec<u32>
pub fn pids_in_cgroup(&self, name: &str) -> Vec<u32>
PIDs currently in the named child cgroup (empty if it doesn’t exist).
Sourcepub fn sweep_guard_leftovers(&self) -> Result<()>
pub fn sweep_guard_leftovers(&self) -> Result<()>
Startup recovery: thaw and clean up every leftover guard-<pid>
cgroup so no process is left frozen after a prior crash.
Legacy: pre-act-in-place rlm-guard builds moved a target process into
its own guard-<pid> cgroup to freeze/cap it; the guard now acts in
place on the process’s existing cgroup (journal-backed, see
guard/effector.rs) and never creates guard-<pid> cgroups itself.
This sweep only exists to clean up leftovers from an upgrade across
that change and can be removed after one release.