Skip to content

Commit a8fb144

Browse files
authored
[crashtracker] Names for SI_CODEs (#875)
1 parent 4c831d1 commit a8fb144

File tree

9 files changed

+539
-223
lines changed

9 files changed

+539
-223
lines changed

Cargo.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LICENSE-3rdparty.yml

Lines changed: 40 additions & 6 deletions
Large diffs are not rendered by default.

bin_tests/src/bin/crashtracker_bin_test.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ fn main() -> anyhow::Result<()> {
1313
mod unix {
1414
use anyhow::Context;
1515
use bin_tests::modes::behavior::get_behavior;
16-
use nix::sys::signal::{raise, Signal};
16+
use nix::{
17+
sys::signal::{kill, raise, Signal},
18+
unistd::Pid,
19+
};
1720
use std::env;
1821
use std::path::Path;
1922

@@ -100,14 +103,18 @@ mod unix {
100103

101104
crashtracker::begin_op(crashtracker::OpTypes::ProfilerCollectingSample)?;
102105
match crash_typ.as_str() {
106+
"kill_sigabrt" => kill(Pid::this(), Signal::SIGABRT)?,
107+
"kill_sigill" => kill(Pid::this(), Signal::SIGILL)?,
108+
"kill_sigbus" => kill(Pid::this(), Signal::SIGBUS)?,
109+
"kill_sigsegv" => kill(Pid::this(), Signal::SIGSEGV)?,
103110
"null_deref" => {
104111
let x = unsafe { deref_ptr(std::ptr::null_mut::<u8>()) };
105112
println!("{x}");
106113
}
107-
"sigabrt" => raise(Signal::SIGABRT)?,
108-
"sigill" => raise(Signal::SIGILL)?,
109-
"sigbus" => raise(Signal::SIGBUS)?,
110-
"sigsegv" => raise(Signal::SIGSEGV)?,
114+
"raise_sigabrt" => raise(Signal::SIGABRT)?,
115+
"raise_sigill" => raise(Signal::SIGILL)?,
116+
"raise_sigbus" => raise(Signal::SIGBUS)?,
117+
"raise_sigsegv" => raise(Signal::SIGSEGV)?,
111118
_ => anyhow::bail!("Unexpected crash_typ: {crash_typ}"),
112119
}
113120
crashtracker::end_op(crashtracker::OpTypes::ProfilerCollectingSample)?;

bin_tests/tests/crashtracker_bin_test.rs

Lines changed: 134 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -69,30 +69,58 @@ fn test_crash_tracking_bin_fork() {
6969

7070
#[test]
7171
#[cfg_attr(miri, ignore)]
72-
fn test_crash_tracking_bin_abort() {
72+
fn test_crash_tracking_bin_kill_sigabrt() {
7373
// For now, do the base test (donothing). For future we should probably also test chaining.
74-
test_crash_tracking_bin(BuildProfile::Release, "donothing", "sigabrt");
74+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "kill_sigabrt");
7575
}
7676

7777
#[test]
7878
#[cfg_attr(miri, ignore)]
79-
fn test_crash_tracking_bin_sigill() {
79+
fn test_crash_tracking_bin_kill_sigill() {
8080
// For now, do the base test (donothing). For future we should probably also test chaining.
81-
test_crash_tracking_bin(BuildProfile::Release, "donothing", "sigill");
81+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "kill_sigill");
8282
}
8383

8484
#[test]
8585
#[cfg_attr(miri, ignore)]
86-
fn test_crash_tracking_bin_sigbus() {
86+
fn test_crash_tracking_bin_kill_sigbus() {
8787
// For now, do the base test (donothing). For future we should probably also test chaining.
88-
test_crash_tracking_bin(BuildProfile::Release, "donothing", "sigbus");
88+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "kill_sigbus");
8989
}
9090

9191
#[test]
9292
#[cfg_attr(miri, ignore)]
93-
fn test_crash_tracking_bin_sigsegv() {
93+
fn test_crash_tracking_bin_kill_sigsegv() {
9494
// For now, do the base test (donothing). For future we should probably also test chaining.
95-
test_crash_tracking_bin(BuildProfile::Release, "donothing", "sigsegv");
95+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "kill_sigsegv");
96+
}
97+
98+
#[test]
99+
#[cfg_attr(miri, ignore)]
100+
fn test_crash_tracking_bin_raise_sigabrt() {
101+
// For now, do the base test (donothing). For future we should probably also test chaining.
102+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "raise_sigabrt");
103+
}
104+
105+
#[test]
106+
#[cfg_attr(miri, ignore)]
107+
fn test_crash_tracking_bin_raise_sigill() {
108+
// For now, do the base test (donothing). For future we should probably also test chaining.
109+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "raise_sigill");
110+
}
111+
112+
#[test]
113+
#[cfg_attr(miri, ignore)]
114+
fn test_crash_tracking_bin_raise_sigbus() {
115+
// For now, do the base test (donothing). For future we should probably also test chaining.
116+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "raise_sigbus");
117+
}
118+
119+
#[test]
120+
#[cfg_attr(miri, ignore)]
121+
fn test_crash_tracking_bin_raise_sigsegv() {
122+
// For now, do the base test (donothing). For future we should probably also test chaining.
123+
test_crash_tracking_bin(BuildProfile::Release, "donothing", "raise_sigsegv");
96124
}
97125

98126
fn test_crash_tracking_bin(
@@ -122,8 +150,12 @@ fn test_crash_tracking_bin(
122150
// Not sure why sigill behaves differently??
123151
// TODO: figure that out.
124152
match crash_typ {
125-
"null_deref" | "sigabrt" | "sigill" => assert!(!exit_status.success()),
126-
"sigbus" | "sigsegv" => (),
153+
"kill_sigabrt" | "kill_sigill" | "null_deref" | "raise_sigabrt" | "raise_sigill" => {
154+
assert!(!exit_status.success())
155+
}
156+
"kill_sigbus" | "kill_sigsegv" | "raise_sigbus" | "raise_sigsegv" => {
157+
assert!(exit_status.success())
158+
}
127159
_ => unreachable!("{crash_typ} shouldn't happen"),
128160
}
129161

@@ -186,39 +218,72 @@ fn test_crash_tracking_bin(
186218

187219
fn assert_siginfo_message(sig_info: &Value, crash_typ: &str) {
188220
match crash_typ {
189-
"sigabrt" => {
190-
assert_eq!(sig_info["si_code_human_readable"], "UNKNOWN");
221+
"null_deref" =>
222+
// On every platform other than OSX ARM, the si_code is 1: SEGV_MAPERR
223+
// On OSX ARM, its 2: SEGV_ACCERR
224+
{
225+
assert_eq!(sig_info["si_addr"], "0x0000000000000000");
226+
assert!(
227+
sig_info["si_code"] == 2 || sig_info["si_code"] == 1,
228+
"{sig_info:?}"
229+
);
230+
assert!(
231+
sig_info["si_code_human_readable"] == "SEGV_ACCERR"
232+
|| sig_info["si_code_human_readable"] == "SEGV_MAPERR",
233+
"{sig_info:?}"
234+
);
235+
assert_eq!(sig_info["si_signo"], libc::SIGSEGV);
236+
assert_eq!(sig_info["si_signo_human_readable"], "SIGSEGV");
237+
}
238+
239+
"kill_sigabrt" => {
191240
assert_eq!(sig_info["si_signo"], libc::SIGABRT);
192241
assert_eq!(sig_info["si_signo_human_readable"], "SIGABRT");
242+
// https://vorner.github.io/2021/01/03/dark-side-of-posix-apis.html
243+
// OSX signal handling is the worst.
244+
#[cfg(not(target_os = "macos"))]
245+
assert_eq!(sig_info["si_code_human_readable"], "SI_USER");
193246
}
194-
"sigsegv" => {
195-
assert_eq!(sig_info["si_code_human_readable"], "UNKNOWN");
247+
"kill_sigsegv" => {
196248
assert_eq!(sig_info["si_signo"], libc::SIGSEGV);
197249
assert_eq!(sig_info["si_signo_human_readable"], "SIGSEGV");
250+
// https://vorner.github.io/2021/01/03/dark-side-of-posix-apis.html
251+
// OSX signal handling is the worst.
252+
#[cfg(not(target_os = "macos"))]
253+
assert_eq!(sig_info["si_code_human_readable"], "SI_USER");
198254
}
199-
"sigbus" => {
200-
assert_eq!(sig_info["si_code_human_readable"], "UNKNOWN");
255+
"kill_sigbus" => {
201256
assert_eq!(sig_info["si_signo"], libc::SIGBUS);
202257
assert_eq!(sig_info["si_signo_human_readable"], "SIGBUS");
258+
// https://vorner.github.io/2021/01/03/dark-side-of-posix-apis.html
259+
// OSX signal handling is the worst.
260+
#[cfg(not(target_os = "macos"))]
261+
assert_eq!(sig_info["si_code_human_readable"], "SI_USER");
203262
}
204-
"sigill" => {
205-
assert_eq!(sig_info["si_code_human_readable"], "UNKNOWN");
263+
"kill_sigill" => {
206264
assert_eq!(sig_info["si_signo"], libc::SIGILL);
207265
assert_eq!(sig_info["si_signo_human_readable"], "SIGILL");
266+
// https://vorner.github.io/2021/01/03/dark-side-of-posix-apis.html
267+
// OSX signal handling is the worst.
268+
#[cfg(not(target_os = "macos"))]
269+
assert_eq!(sig_info["si_code_human_readable"], "SI_USER");
208270
}
209-
"null_deref" =>
210-
// On every platform other than OSX ARM, the si_code is 1: SEGV_MAPERR
211-
// On OSX ARM, its 2: SEGV_ACCERR
212-
{
213-
assert_eq!(sig_info["si_addr"], "0x0000000000000000");
214-
assert!(
215-
sig_info["si_code"] == 2 || sig_info["si_code"] == 1,
216-
"{sig_info:?}"
217-
);
218-
assert_eq!(sig_info["si_code_human_readable"], "UNKNOWN");
271+
"raise_sigabrt" => {
272+
assert_eq!(sig_info["si_signo"], libc::SIGABRT);
273+
assert_eq!(sig_info["si_signo_human_readable"], "SIGABRT");
274+
}
275+
"raise_sigsegv" => {
219276
assert_eq!(sig_info["si_signo"], libc::SIGSEGV);
220277
assert_eq!(sig_info["si_signo_human_readable"], "SIGSEGV");
221278
}
279+
"raise_sigbus" => {
280+
assert_eq!(sig_info["si_signo"], libc::SIGBUS);
281+
assert_eq!(sig_info["si_signo_human_readable"], "SIGBUS");
282+
}
283+
"raise_sigill" => {
284+
assert_eq!(sig_info["si_signo"], libc::SIGILL);
285+
assert_eq!(sig_info["si_signo_human_readable"], "SIGILL");
286+
}
222287
_ => panic!("unexpected crash_typ {crash_typ}"),
223288
}
224289
}
@@ -260,44 +325,68 @@ fn assert_telemetry_message(crash_telemetry: &[u8], crash_typ: &str) {
260325
]);
261326

262327
match crash_typ {
263-
"sigabrt" => {
328+
"null_deref" => {
329+
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
330+
assert!(tags.contains("si_addr:0x0000000000000000"), "{tags:?}");
331+
assert!(
332+
tags.contains("si_code_human_readable:SEGV_ACCERR")
333+
|| tags.contains("si_code_human_readable:SEGV_MAPERR"),
334+
"{tags:?}"
335+
);
336+
assert!(tags.contains("si_signo_human_readable:SIGSEGV"), "{tags:?}");
337+
assert!(tags.contains("si_signo:11"), "{tags:?}");
338+
assert!(
339+
tags.contains("si_code:1") || tags.contains("si_code:2"),
340+
"{tags:?}"
341+
);
342+
}
343+
"kill_sigabrt" => {
264344
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
265-
assert!(tags.contains("si_code_human_readable:UNKNOWN"), "{tags:?}");
266345
assert!(tags.contains("si_signo_human_readable:SIGABRT"), "{tags:?}");
267346
assert!(tags.contains("si_signo:6"), "{tags:?}");
268347
}
269-
"sigbus" => {
348+
"kill_sigill" => {
349+
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
350+
assert!(tags.contains("si_signo_human_readable:SIGILL"), "{tags:?}");
351+
assert!(tags.contains("si_signo:4"), "{tags:?}");
352+
}
353+
"kill_sigbus" => {
270354
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
271-
assert!(tags.contains("si_code_human_readable:UNKNOWN"), "{tags:?}");
272355
assert!(tags.contains("si_signo_human_readable:SIGBUS"), "{tags:?}");
273356
// SIGBUS can be 7 or 10, depending on the os.
274357
assert!(
275358
tags.contains(format!("si_signo:{}", libc::SIGBUS).as_str()),
276359
"{tags:?}"
277360
);
278361
}
279-
"sigill" => {
362+
"kill_sigsegv" => {
363+
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
364+
assert!(tags.contains("si_signo_human_readable:SIGSEGV"), "{tags:?}");
365+
assert!(tags.contains("si_signo:11"), "{tags:?}");
366+
}
367+
"raise_sigabrt" => {
368+
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
369+
assert!(tags.contains("si_signo_human_readable:SIGABRT"), "{tags:?}");
370+
assert!(tags.contains("si_signo:6"), "{tags:?}");
371+
}
372+
"raise_sigill" => {
280373
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
281-
assert!(tags.contains("si_code_human_readable:UNKNOWN"), "{tags:?}");
282374
assert!(tags.contains("si_signo_human_readable:SIGILL"), "{tags:?}");
283375
assert!(tags.contains("si_signo:4"), "{tags:?}");
284376
}
285-
"sigsegv" => {
377+
"raise_sigbus" => {
286378
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
287-
assert!(tags.contains("si_code_human_readable:UNKNOWN"), "{tags:?}");
288-
assert!(tags.contains("si_signo_human_readable:SIGSEGV"), "{tags:?}");
289-
assert!(tags.contains("si_signo:11"), "{tags:?}");
379+
assert!(tags.contains("si_signo_human_readable:SIGBUS"), "{tags:?}");
380+
// SIGBUS can be 7 or 10, depending on the os.
381+
assert!(
382+
tags.contains(format!("si_signo:{}", libc::SIGBUS).as_str()),
383+
"{tags:?}"
384+
);
290385
}
291-
"null_deref" => {
386+
"raise_sigsegv" => {
292387
assert!(base_expected_tags.is_subset(&tags), "{tags:?}");
293-
assert!(tags.contains("si_addr:0x0000000000000000"), "{tags:?}");
294-
assert!(tags.contains("si_code_human_readable:UNKNOWN"), "{tags:?}");
295388
assert!(tags.contains("si_signo_human_readable:SIGSEGV"), "{tags:?}");
296389
assert!(tags.contains("si_signo:11"), "{tags:?}");
297-
assert!(
298-
tags.contains("si_code:1") || tags.contains("si_code:2"),
299-
"{tags:?}"
300-
);
301390
}
302391
_ => panic!("{crash_typ}"),
303392
}

crashtracker/Cargo.toml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,26 @@ anyhow = "1.0"
3232
backtrace = "0.3.74"
3333
chrono = {version = "0.4", default-features = false, features = ["std", "clock", "serde"]}
3434
ddcommon = {path = "../ddcommon"}
35+
ddtelemetry = {path = "../ddtelemetry"}
36+
http = "0.2"
3537
hyper = {version = "0.14", features = ["client", "backports", "deprecated"], default-features = false}
3638
libc = "0.2"
3739
nix = { version = "0.27.1", features = ["poll", "signal", "socket"] }
40+
num-derive = "0.4.2"
41+
num-traits = "0.2.19"
3842
os_info = "3.7.0"
3943
page_size = "0.6.0"
40-
serde = {version = "1.0", features = ["derive"]}
41-
serde_json = {version = "1.0"}
42-
uuid = { version = "1.4.1", features = ["v4", "serde"] }
43-
ddtelemetry = {path = "../ddtelemetry"}
44-
tokio = { version = "1.23", features = ["rt", "macros", "io-std", "io-util"] }
45-
http = "0.2"
4644
portable-atomic = { version = "1.6.0", features = ["serde"] }
4745
rand = "0.8.5"
4846
schemars = "0.8.21"
47+
serde = {version = "1.0", features = ["derive"]}
48+
serde_json = {version = "1.0"}
49+
tokio = { version = "1.23", features = ["rt", "macros", "io-std", "io-util"] }
50+
uuid = { version = "1.4.1", features = ["v4", "serde"] }
4951

5052
[dev-dependencies]
5153
tempfile = { version = "3.3" }
54+
55+
[build-dependencies]
56+
# If we use a newer version of cc, CI fails on alpine.
57+
cc = "1.1.31"

crashtracker/build.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2025-Present Datadog, Inc. https://www.datadoghq.com/
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
#[cfg(unix)]
5+
fn main() {
6+
cc::Build::new()
7+
.file("src/crash_info/emit_sicodes.c")
8+
.compile("emit_sicodes");
9+
}
10+
11+
#[cfg(not(unix))]
12+
fn main() {}

0 commit comments

Comments
 (0)