Skip to main content

ghostscope_process/pid/
resolve.rs

1use super::procfs::{
2    process_exists, read_nspid_chain, read_nspid_chain_from_status, read_pid_ns_id, read_status,
3};
4use super::types::{PidResolveSource, PidViews};
5
6pub fn resolve_input_pid(input_pid: u32) -> anyhow::Result<PidViews> {
7    if !process_exists(input_pid) {
8        return Err(anyhow::anyhow!(
9            "Process with PID {} is not running. Use 'ps -p {}' to verify the process exists.\n\
10             Additional check: -p expects a PID visible in the current PID namespace.",
11            input_pid,
12            input_pid
13        ));
14    }
15
16    resolve_proc_pid(input_pid)
17}
18
19pub fn resolve_proc_pid(proc_pid: u32) -> anyhow::Result<PidViews> {
20    let status = read_status(proc_pid)?;
21    let nspid_chain = read_nspid_chain_from_status(&status);
22    let host_pid = nspid_chain
23        .as_ref()
24        .and_then(|chain| chain.first().copied())
25        .unwrap_or(proc_pid);
26    let container_pid = nspid_chain.as_ref().and_then(|chain| chain.last().copied());
27
28    Ok(PidViews {
29        proc_pid,
30        host_pid,
31        container_pid,
32        pid_ns: read_pid_ns_id(proc_pid),
33        nspid_chain,
34        source: PidResolveSource::DirectProcStatus,
35    })
36}
37
38pub fn host_pid_for_proc_pid(proc_pid: u32) -> u32 {
39    read_nspid_chain(proc_pid)
40        .and_then(|chain| chain.first().copied())
41        .unwrap_or(proc_pid)
42}
43
44/// Resolve a kernel event PID (initial PID namespace) to the `/proc` PID in the
45/// current userspace namespace when possible.
46pub fn resolve_proc_pid_for_event(event_pid: u32) -> u32 {
47    if std::path::Path::new(&format!("/proc/{event_pid}")).exists() {
48        return event_pid;
49    }
50
51    if let Ok(dir) = std::fs::read_dir("/proc") {
52        for ent in dir.flatten() {
53            let file_name = ent.file_name();
54            let Ok(proc_pid) = file_name.to_string_lossy().parse::<u32>() else {
55                continue;
56            };
57            let Some(chain) = read_nspid_chain(proc_pid) else {
58                continue;
59            };
60            if chain.first().copied() == Some(event_pid) {
61                return proc_pid;
62            }
63        }
64    }
65
66    event_pid
67}
68
69/// Resolve a `/proc` PID back to the host-view event PID when possible.
70pub fn resolve_event_pid_for_proc(proc_pid: u32) -> u32 {
71    read_nspid_chain(proc_pid)
72        .and_then(|chain| chain.first().copied())
73        .unwrap_or(proc_pid)
74}