Skip to main content

ghostscope_process/pid/
session.rs

1use std::fmt;
2
3use tracing::warn;
4
5use super::{
6    build_runtime_pid_plan, detect_runtime_environment, resolve_input_pid, PidModeFailFast,
7    PidViews, RuntimeEnvironmentInfo, RuntimePidPlan, RuntimePidPlanInput,
8};
9
10#[derive(Debug)]
11pub enum ResolvePidSessionError {
12    Resolve(anyhow::Error),
13    FailFast(PidModeFailFast),
14}
15
16impl fmt::Display for ResolvePidSessionError {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        match self {
19            ResolvePidSessionError::Resolve(err) => write!(f, "{err}"),
20            ResolvePidSessionError::FailFast(PidModeFailFast { proc_pid }) => {
21                write!(f, "PID mode is not reliable for proc pid {proc_pid}")
22            }
23        }
24    }
25}
26
27impl std::error::Error for ResolvePidSessionError {
28    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
29        match self {
30            ResolvePidSessionError::Resolve(err) => Some(err.as_ref()),
31            ResolvePidSessionError::FailFast(_) => None,
32        }
33    }
34}
35
36impl From<anyhow::Error> for ResolvePidSessionError {
37    fn from(value: anyhow::Error) -> Self {
38        ResolvePidSessionError::Resolve(value)
39    }
40}
41
42#[derive(Debug, Clone)]
43pub struct ResolvedPidSession {
44    pub runtime_env: RuntimeEnvironmentInfo,
45    pub target_pid_views: Option<PidViews>,
46    pub self_pid_views: Option<PidViews>,
47    pub runtime_pid_plan: RuntimePidPlan,
48}
49
50pub fn resolve_pid_session(
51    input_pid: Option<u32>,
52    helper_supported: bool,
53) -> Result<ResolvedPidSession, ResolvePidSessionError> {
54    let runtime_env = detect_runtime_environment();
55    let in_container = runtime_env.is_container_likely();
56
57    let target_pid_views = input_pid.map(resolve_input_pid).transpose()?;
58    let self_pid_views = if helper_supported {
59        let self_pid = std::process::id();
60        match resolve_input_pid(self_pid) {
61            Ok(pid_views) => Some(pid_views),
62            Err(err) => {
63                warn!(
64                    "Failed to resolve self PID namespace context (self pid={}): {}",
65                    self_pid, err
66                );
67                None
68            }
69        }
70    } else {
71        None
72    };
73
74    let runtime_pid_plan = build_runtime_pid_plan(RuntimePidPlanInput {
75        target_pid_views: target_pid_views.as_ref(),
76        self_pid_views: self_pid_views.as_ref(),
77        in_container,
78        helper_supported,
79    })
80    .map_err(ResolvePidSessionError::FailFast)?;
81
82    Ok(ResolvedPidSession {
83        runtime_env,
84        target_pid_views,
85        self_pid_views,
86        runtime_pid_plan,
87    })
88}