reno/linux/
process.rs

1use anyhow::{Context, Result};
2use nix::{
3    sched::{self, CloneFlags},
4    unistd::Pid,
5};
6use oci_spec::runtime::LinuxNamespace;
7use procfs::process::{ProcState, Process};
8
9use crate::linux::namespace;
10
11/// `clone_child` creates a child process that invokes `function` in seperated
12/// Linux namespaces specified in `namespace_list`.
13/// For more information, see the [clone(2)](https://man7.org/linux/man-pages/man2/clone.2.html)
14/// man page.
15pub fn clone_child(
16    namespace_list: &[LinuxNamespace],
17    child_fn: impl FnMut() -> isize,
18) -> Result<Pid> {
19    const STACK_SIZE: usize = 4 * 1024 * 1024;
20    let mut stack: [u8; STACK_SIZE] = [0; STACK_SIZE];
21
22    let clone_flags = namespace_list
23        .iter()
24        .map(namespace::linux_namespace_to_clone_flags)
25        .reduce(|flag_1, flag_2| flag_1 | flag_2)
26        .unwrap_or(CloneFlags::empty());
27
28    let pid = sched::clone(Box::new(child_fn), &mut stack, clone_flags, None)
29        .context("failed to clone the container process")?;
30    Ok(pid)
31}
32
33/// `inspect_process` inspects the status of the process in `/proc/<pid>/stat`
34/// and returns a variant of the [ProcState] enum that represents the process status.
35pub fn inspect_process(pid: i32) -> Result<ProcState> {
36    let process = Process::new(pid).context(format!("failed to inspect the process {}", pid))?;
37    let process_stat = process
38        .stat()
39        .context(format!("failed to inspect the status of process {}", pid))?;
40    let state = process_stat
41        .state()
42        .context(format!("failed to inspect the state of process {}", pid))?;
43    Ok(state)
44}