Skip to content

Commit 24cbf67

Browse files
authored
feat(crashtracking)!: update crashtracker config ffi to have values for collect all thread config (#1959)
# What does this PR do? [feat(crashtracking)!: collect all threads](#1878) added the functionality to collect all threads. We should expose the config vals for this # Motivation What inspired you to submit this pull request? # Additional Notes Anything else we should know when reviewing? # How to test the change? ``` pub struct Config<'a> { pub additional_files: Slice<'a, CharSlice<'a>>, /// If true, the receiver will collect stack traces for all threads in the crashing process /// (not just the crashing thread) using ptrace-based remote unwinding. pub collect_all_threads: bool, *******THIS IS NEW******* pub create_alt_stack: bool, pub demangle_names: bool, /// The endpoint to send the crash report to (can be a file://). /// If None, the crashtracker will infer the agent host from env variables. pub endpoint: EndpointConfig<'a>, /// Maximum number of non-crashing threads to collect when `collect_all_threads` is true. /// If 0, uses the default (`libdd_crashtracker::default_max_threads()`). pub max_threads: usize, *******THIS IS NEW******* /// Optional filename for a unix domain socket if the receiver is used asynchonously pub optional_unix_socket_filename: CharSlice<'a>, pub resolve_frames: StacktraceCollection, /// The set of signals we should be registered for. /// If empty, use the default set. pub signals: Slice<'a, i32>, /// Timeout in milliseconds before the signal handler starts tearing things down to return. /// If 0, uses the default timeout as specified in /// `libdd_crashtracker::shared::constants::DD_CRASHTRACK_DEFAULT_TIMEOUT`. Otherwise, uses /// the specified timeout value. /// This is given as a uint32_t, but the actual timeout needs to fit inside of an i32 (max /// 2^31-1). This is a limitation of the various interfaces used to guarantee the timeout. pub timeout_ms: u32, pub use_alt_stack: bool, } ```
1 parent a8f0aaa commit 24cbf67

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

examples/ffi/crashtracking.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ int main(int argc, char **argv) {
8686
// Get the default signals and explicitly use them.
8787
struct ddog_crasht_Slice_CInt signals = ddog_crasht_default_signals();
8888
ddog_crasht_Config config = {
89+
.collect_all_threads = true,
90+
.max_threads = 0, // 0 uses the default (libdd_crashtracker::default_max_threads())
8991
.create_alt_stack = false,
9092
.endpoint = {.url = slice(report_path)},
9193
.resolve_frames = DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_INPROCESS_SYMBOLS,

libdd-crashtracker-ffi/src/collector/datatypes.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,17 @@ pub struct EndpointConfig<'a> {
6565
#[repr(C)]
6666
pub struct Config<'a> {
6767
pub additional_files: Slice<'a, CharSlice<'a>>,
68+
/// If true, the receiver will collect stack traces for all threads in the crashing process
69+
/// (not just the crashing thread) using ptrace-based remote unwinding.
70+
pub collect_all_threads: bool,
6871
pub create_alt_stack: bool,
6972
pub demangle_names: bool,
7073
/// The endpoint to send the crash report to (can be a file://).
7174
/// If None, the crashtracker will infer the agent host from env variables.
7275
pub endpoint: EndpointConfig<'a>,
76+
/// Maximum number of non-crashing threads to collect when `collect_all_threads` is true.
77+
/// If 0, uses the default (`libdd_crashtracker::default_max_threads()`).
78+
pub max_threads: usize,
7379
/// Optional filename for a unix domain socket if the receiver is used asynchonously
7480
pub optional_unix_socket_filename: CharSlice<'a>,
7581
pub resolve_frames: StacktraceCollection,
@@ -98,12 +104,16 @@ impl<'a> TryFrom<Config<'a>> for libdd_crashtracker::CrashtrackerConfiguration {
98104
};
99105
let mut builder = Self::builder()
100106
.additional_files(additional_files)
107+
.collect_all_threads(value.collect_all_threads)
101108
.create_alt_stack(value.create_alt_stack)
102109
.demangle_names(value.demangle_names)
103110
.resolve_frames(value.resolve_frames)
104111
.signals(value.signals.iter().copied().collect())
105112
.use_alt_stack(value.use_alt_stack)
106113
.endpoint_use_system_resolver(value.endpoint.use_system_resolver);
114+
if value.max_threads != 0 {
115+
builder = builder.max_threads(value.max_threads);
116+
}
107117
if let Some(api_key) = value.endpoint.api_key.try_to_string_option()? {
108118
builder = builder.endpoint_api_key(&api_key);
109119
}
@@ -150,6 +160,7 @@ mod tests {
150160
fn create_config_default<'a>() -> Config<'a> {
151161
Config {
152162
additional_files: Slice::empty(),
163+
collect_all_threads: false,
153164
create_alt_stack: false,
154165
demangle_names: false,
155166
endpoint: EndpointConfig {
@@ -159,6 +170,7 @@ mod tests {
159170
use_system_resolver: false,
160171
timeout: 0,
161172
},
173+
max_threads: 0,
162174
optional_unix_socket_filename: CharSlice::empty(),
163175
resolve_frames: StacktraceCollection::Disabled,
164176
signals: Slice::empty(),
@@ -167,6 +179,40 @@ mod tests {
167179
}
168180
}
169181

182+
#[test]
183+
fn test_config_try_from_collect_all_threads() -> anyhow::Result<()> {
184+
let mut ffi_config = create_config_default();
185+
ffi_config.collect_all_threads = true;
186+
let config = CrashtrackerConfiguration::try_from(ffi_config)?;
187+
let expected = CrashtrackerConfiguration::builder()
188+
.collect_all_threads(true)
189+
.build()?;
190+
assert_eq!(config, expected);
191+
Ok(())
192+
}
193+
194+
#[test]
195+
fn test_config_try_from_max_threads_zero_uses_default() -> anyhow::Result<()> {
196+
let mut ffi_config = create_config_default();
197+
ffi_config.max_threads = 0;
198+
let config = CrashtrackerConfiguration::try_from(ffi_config)?;
199+
let expected = CrashtrackerConfiguration::builder().build()?;
200+
assert_eq!(config.max_threads(), expected.max_threads());
201+
Ok(())
202+
}
203+
204+
#[test]
205+
fn test_config_try_from_max_threads_custom() -> anyhow::Result<()> {
206+
let mut ffi_config = create_config_default();
207+
ffi_config.max_threads = 512;
208+
let config = CrashtrackerConfiguration::try_from(ffi_config)?;
209+
let expected = CrashtrackerConfiguration::builder()
210+
.max_threads(512)
211+
.build()?;
212+
assert_eq!(config, expected);
213+
Ok(())
214+
}
215+
170216
#[test]
171217
fn test_config_try_from_defaults() -> anyhow::Result<()> {
172218
let ffi_config = create_config_default();

0 commit comments

Comments
 (0)