diff --git a/crashtracker/src/constants.rs b/crashtracker/src/constants.rs index 1a790f627..52b901f7d 100644 --- a/crashtracker/src/constants.rs +++ b/crashtracker/src/constants.rs @@ -5,6 +5,7 @@ pub const DD_CRASHTRACK_BEGIN_CONFIG: &str = "DD_CRASHTRACK_BEGIN_CONFIG"; pub const DD_CRASHTRACK_BEGIN_COUNTERS: &str = "DD_CRASHTRACK_BEGIN_COUNTERS"; pub const DD_CRASHTRACK_BEGIN_FILE: &str = "DD_CRASHTRACK_BEGIN_FILE"; pub const DD_CRASHTRACK_BEGIN_METADATA: &str = "DD_CRASHTRACK_BEGIN_METADATA"; +pub const DD_CRASHTRACK_BEGIN_PROCINFO: &str = "DD_CRASHTRACK_BEGIN_PROCESSINFO"; pub const DD_CRASHTRACK_BEGIN_SIGINFO: &str = "DD_CRASHTRACK_BEGIN_SIGINFO"; pub const DD_CRASHTRACK_BEGIN_STACKTRACE: &str = "DD_CRASHTRACK_BEGIN_STACKTRACE"; pub const DD_CRASHTRACK_DONE: &str = "DD_CRASHTRACK_DONE"; @@ -12,5 +13,6 @@ pub const DD_CRASHTRACK_END_CONFIG: &str = "DD_CRASHTRACK_END_CONFIG"; pub const DD_CRASHTRACK_END_COUNTERS: &str = "DD_CRASHTRACK_END_COUNTERS"; pub const DD_CRASHTRACK_END_FILE: &str = "DD_CRASHTRACK_END_FILE"; pub const DD_CRASHTRACK_END_METADATA: &str = "DD_CRASHTRACK_END_METADATA"; +pub const DD_CRASHTRACK_END_PROCINFO: &str = "DD_CRASHTRACK_END_PROCESSINFO"; pub const DD_CRASHTRACK_END_SIGINFO: &str = "DD_CRASHTRACK_END_SIGINFO"; pub const DD_CRASHTRACK_END_STACKTRACE: &str = "DD_CRASHTRACK_END_STACKTRACE"; diff --git a/crashtracker/src/crash_handler.rs b/crashtracker/src/crash_handler.rs index 6afdfe4ff..762c7cdf4 100644 --- a/crashtracker/src/crash_handler.rs +++ b/crashtracker/src/crash_handler.rs @@ -323,6 +323,14 @@ fn emit_metadata(w: &mut impl Write, metadata_str: &str) -> anyhow::Result<()> { Ok(()) } +fn emit_procinfo(w: &mut impl Write) -> anyhow::Result<()> { + writeln!(w, "{DD_CRASHTRACK_BEGIN_PROCINFO}")?; + let pid = nix::unistd::getpid(); + writeln!(w, "{{\"pid\": {pid} }}")?; + writeln!(w, "{DD_CRASHTRACK_END_PROCINFO}")?; + Ok(()) +} + fn emit_siginfo(w: &mut impl Write, signum: i32) -> anyhow::Result<()> { let signame = if signum == libc::SIGSEGV { "SIGSEGV" @@ -348,6 +356,7 @@ fn emit_crashreport( emit_metadata(pipe, metadata_string)?; emit_config(pipe, config_str)?; emit_siginfo(pipe, signum)?; + emit_procinfo(pipe)?; pipe.flush()?; emit_counters(pipe)?; pipe.flush()?; diff --git a/crashtracker/src/crash_info.rs b/crashtracker/src/crash_info.rs index ede2629b8..bd6639310 100644 --- a/crashtracker/src/crash_info.rs +++ b/crashtracker/src/crash_info.rs @@ -47,6 +47,11 @@ pub struct SigInfo { pub signame: Option, } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ProcessInfo { + pub pid: u32, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct CrashInfo { #[serde(skip_serializing_if = "HashMap::is_empty")] @@ -64,6 +69,9 @@ pub struct CrashInfo { pub os_info: os_info::Info, #[serde(skip_serializing_if = "Option::is_none")] #[serde(default)] + pub proc_info: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] pub siginfo: Option, #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default)] @@ -126,6 +134,7 @@ impl CrashInfo { incomplete: false, metadata: None, os_info, + proc_info: None, siginfo: None, stacktrace: vec![], tags: HashMap::new(), @@ -180,6 +189,12 @@ impl CrashInfo { Ok(()) } + pub fn set_procinfo(&mut self, proc_info: ProcessInfo) -> anyhow::Result<()> { + anyhow::ensure!(self.proc_info.is_none()); + self.proc_info = Some(proc_info); + Ok(()) + } + pub fn set_siginfo(&mut self, siginfo: SigInfo) -> anyhow::Result<()> { anyhow::ensure!(self.siginfo.is_none()); self.siginfo = Some(siginfo); diff --git a/crashtracker/src/receiver.rs b/crashtracker/src/receiver.rs index 3bd850b91..385c300cf 100644 --- a/crashtracker/src/receiver.rs +++ b/crashtracker/src/receiver.rs @@ -4,7 +4,6 @@ use super::*; use anyhow::Context; -use nix::unistd::getppid; use std::{io::BufReader, os::unix::net::UnixListener}; pub fn resolve_frames( @@ -12,11 +11,11 @@ pub fn resolve_frames( crash_info: &mut CrashInfo, ) -> anyhow::Result<()> { if config.resolve_frames == StacktraceCollection::EnabledWithSymbolsInReceiver { - // The receiver is the direct child of the crashing process - // TODO: This pid should be sent over the wire, so that - // it can be used in a sidecar. - let ppid: u32 = getppid().as_raw().try_into()?; - crash_info.resolve_names_from_process(ppid)? + if let Some(proc_info) = &crash_info.proc_info { + crash_info.resolve_names_from_process(proc_info.pid)? + } else { + eprintln!("Unable to resolve frames: No PID specified"); + } } Ok(()) } @@ -84,6 +83,7 @@ enum StdinState { File(String, Vec), InternalError(String), Metadata, + ProcInfo, SigInfo, StackTrace(Vec), Waiting, @@ -147,6 +147,13 @@ fn process_line( StdinState::Metadata } + StdinState::ProcInfo if line.starts_with(DD_CRASHTRACK_END_PROCINFO) => StdinState::Waiting, + StdinState::ProcInfo => { + let proc_info = serde_json::from_str(&line)?; + crashinfo.set_procinfo(proc_info)?; + StdinState::ProcInfo + } + StdinState::SigInfo if line.starts_with(DD_CRASHTRACK_END_SIGINFO) => StdinState::Waiting, StdinState::SigInfo => { let siginfo = serde_json::from_str(&line)?; @@ -176,6 +183,9 @@ fn process_line( StdinState::Waiting if line.starts_with(DD_CRASHTRACK_BEGIN_METADATA) => { StdinState::Metadata } + StdinState::Waiting if line.starts_with(DD_CRASHTRACK_BEGIN_PROCINFO) => { + StdinState::ProcInfo + } StdinState::Waiting if line.starts_with(DD_CRASHTRACK_BEGIN_SIGINFO) => StdinState::SigInfo, StdinState::Waiting if line.starts_with(DD_CRASHTRACK_BEGIN_STACKTRACE) => { StdinState::StackTrace(vec![]) diff --git a/crashtracker/src/telemetry.rs b/crashtracker/src/telemetry.rs index ecb137004..f791b4440 100644 --- a/crashtracker/src/telemetry.rs +++ b/crashtracker/src/telemetry.rs @@ -278,6 +278,7 @@ mod tests { signum: 11, signame: Some("SIGSEGV".to_owned()), }), + proc_info: None, stacktrace: vec![], additional_stacktraces: HashMap::new(), tags: HashMap::new(),