Skip to content

Commit

Permalink
[crashtracker] Add option to collect symbols in process (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsn authored May 15, 2024
1 parent 8e73294 commit 74c89eb
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 5 deletions.
2 changes: 1 addition & 1 deletion crashtracker/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ fn test_crash() {
let path_to_receiver_binary =
"/tmp/libdatadog/bin/libdatadog-crashtracking-receiver".to_string();
let create_alt_stack = true;
let resolve_frames = StacktraceCollection::Enabled;
let resolve_frames = StacktraceCollection::EnabledWithInprocessSymbols;
let stderr_filename = Some(format!("{dir}/stderr_{time}.txt"));
let stdout_filename = Some(format!("{dir}/stdout_{time}.txt"));
let timeout = Duration::from_secs(30);
Expand Down
54 changes: 53 additions & 1 deletion crashtracker/src/collectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use anyhow::Context;

use crate::StacktraceCollection;

use super::constants::*;
use std::{
fs::File,
Expand All @@ -22,7 +24,10 @@ use std::{
/// https://github.com/rust-lang/backtrace-rs/issues/414
/// Calculating the `ip` of the frames seems safe, but resolving the frames
/// sometimes crashes.
pub unsafe fn emit_backtrace_by_frames(w: &mut impl Write) -> anyhow::Result<()> {
pub unsafe fn emit_backtrace_by_frames(
w: &mut impl Write,
resolve_frames: StacktraceCollection,
) -> anyhow::Result<()> {
// https://docs.rs/backtrace/latest/backtrace/index.html
writeln!(w, "{DD_CRASHTRACK_BEGIN_STACKTRACE}")?;
backtrace::trace_unsynchronized(|frame| {
Expand All @@ -35,6 +40,53 @@ pub unsafe fn emit_backtrace_by_frames(w: &mut impl Write) -> anyhow::Result<()>
}
write!(w, "\"sp\": \"{:?}\", ", frame.sp()).unwrap();
write!(w, "\"symbol_address\": \"{:?}\"", frame.symbol_address()).unwrap();
if resolve_frames == StacktraceCollection::EnabledWithInprocessSymbols {
write!(w, ", \"names\": [").unwrap();

let mut first = true;
// This can give multiple answers in the case of inlined functions
// https://docs.rs/backtrace/latest/backtrace/fn.resolve.html
// Store them all into an array of names
unsafe {
backtrace::resolve_frame_unsynchronized(frame, |symbol| {
if !first {
write!(w, ", ").unwrap();
}
write!(w, "{{").unwrap();
let mut comma_needed = false;
if let Some(name) = symbol.name() {
write!(w, "\"name\": \"{}\"", name).unwrap();
comma_needed = true;
}
if let Some(filename) = symbol.filename() {
if comma_needed {
write!(w, ", ").unwrap();
}
write!(w, "\"filename\": {:?}", filename).unwrap();
comma_needed = true;
}
if let Some(colno) = symbol.colno() {
if comma_needed {
write!(w, ", ").unwrap();
}
write!(w, "\"colno\": {}", colno).unwrap();
comma_needed = true;
}

if let Some(lineno) = symbol.lineno() {
if comma_needed {
write!(w, ", ").unwrap();
}
write!(w, "\"lineno\": {}", lineno).unwrap();
}

write!(w, "}}").unwrap();

first = false;
});
}
write!(w, "]").unwrap();
}
writeln!(w, "}}").unwrap();
true // keep going to the next frame
});
Expand Down
3 changes: 2 additions & 1 deletion crashtracker/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ pub enum StacktraceCollection {
/// Stacktrace collection occurs in the
Disabled,
WithoutSymbols,
Enabled,
EnabledWithInprocessSymbols,
EnabledWithSymbolsInReceiver,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion crashtracker/src/crash_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ fn handle_posix_signal_impl(signum: i32) -> anyhow::Result<()> {
// https://doc.rust-lang.org/src/std/backtrace.rs.html#332
// Do this last, so even if it crashes, we still get the other info.
if config.resolve_frames != StacktraceCollection::Disabled {
unsafe { emit_backtrace_by_frames(pipe)? };
unsafe { emit_backtrace_by_frames(pipe, config.resolve_frames)? };
}
writeln!(pipe, "{DD_CRASHTRACK_DONE}")?;

Expand Down
2 changes: 1 addition & 1 deletion crashtracker/src/receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub fn resolve_frames(
config: &CrashtrackerConfiguration,
crash_info: &mut CrashInfo,
) -> anyhow::Result<()> {
if config.resolve_frames == StacktraceCollection::Enabled {
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.
Expand Down

0 comments on commit 74c89eb

Please sign in to comment.