ghostscope_process/pid/
resolve.rs1use 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
44pub 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
69pub 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}