Skip to content

Commit c235ddf

Browse files
committed
Windows e2e named pipe test
1 parent 76b8de1 commit c235ddf

File tree

5 files changed

+716
-535
lines changed

5 files changed

+716
-535
lines changed

Cargo.lock

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

bin_tests/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ hex = "0.4"
2424

2525
[target.'cfg(windows)'.dependencies]
2626
tokio = { version = "1.0", features = ["net"] }
27+
windows = { version = "0.58", features = [
28+
"Win32_System_Diagnostics_Debug",
29+
] }
2730

2831
[lib]
2932
bench = false
@@ -42,4 +45,4 @@ bench = false
4245

4346
[[bin]]
4447
name = "crashing_test_app"
45-
bench = false
48+
bench = false

bin_tests/src/bin/crashing_test_app.rs

Lines changed: 145 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
// Copyright 2023-Present Datadog, Inc. https://www.datadoghq.com/
22
// SPDX-License-Identifier: Apache-2.0
33

4-
#[cfg(not(unix))]
5-
fn main() {}
6-
74
#[cfg(unix)]
85
fn main() -> anyhow::Result<()> {
96
unix::main()
107
}
118

9+
#[cfg(windows)]
10+
fn main() -> anyhow::Result<()> {
11+
windows::main()
12+
}
13+
14+
#[cfg(not(any(unix, windows)))]
15+
fn main() -> anyhow::Result<()> {
16+
eprintln!("Crashing test app is only supported on Unix and Windows");
17+
std::process::exit(1);
18+
}
19+
1220
#[cfg(unix)]
1321
mod unix {
1422
use anyhow::ensure;
@@ -104,3 +112,137 @@ mod unix {
104112
Ok(())
105113
}
106114
}
115+
116+
#[cfg(windows)]
117+
mod windows {
118+
use anyhow::Context;
119+
use std::env;
120+
121+
use datadog_crashtracker::{init_crashtracking_windows, Metadata};
122+
use ddcommon::{tag, Endpoint};
123+
124+
#[inline(never)]
125+
unsafe fn fn3() {
126+
// Force a true access violation that WER will catch
127+
// Use inline assembly to avoid Rust's null pointer checks
128+
#[cfg(target_arch = "x86_64")]
129+
{
130+
std::arch::asm!(
131+
"mov rax, 0",
132+
"mov dword ptr [rax], 42",
133+
out("rax") _,
134+
);
135+
}
136+
137+
#[cfg(target_arch = "x86")]
138+
{
139+
std::arch::asm!(
140+
"mov eax, 0",
141+
"mov dword ptr [eax], 42",
142+
out("eax") _,
143+
);
144+
}
145+
146+
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
147+
{
148+
// Fallback for other architectures - this will be a panic, not WER
149+
let null_ptr = std::ptr::null_mut::<i32>();
150+
*null_ptr = 42;
151+
}
152+
}
153+
154+
#[inline(never)]
155+
fn fn2() {
156+
unsafe { fn3() }
157+
}
158+
159+
#[inline(never)]
160+
fn fn1() {
161+
fn2()
162+
}
163+
164+
#[inline(never)]
165+
pub fn main() -> anyhow::Result<()> {
166+
println!("Windows crashing test app starting...");
167+
168+
// Parse arguments: output_url
169+
let mut args = env::args().skip(1);
170+
let output_url = args.next().context("Expected output_url argument")?;
171+
172+
// Check environment variables for named pipe configuration
173+
if let Ok(pipe_name) = env::var("DD_TRACE_PIPE_NAME") {
174+
println!("Using named pipe: {}", pipe_name);
175+
}
176+
177+
if let Ok(errors_intake) = env::var("_DD_ERRORS_INTAKE_ENABLED") {
178+
println!("Errors intake enabled: {}", errors_intake);
179+
}
180+
181+
if let Ok(api_key) = env::var("DD_API_KEY") {
182+
println!("API key configured (length: {})", api_key.len());
183+
}
184+
185+
if let Ok(direct_submission) = env::var("_DD_DIRECT_SUBMISSION_ENABLED") {
186+
println!("Direct submission enabled: {}", direct_submission);
187+
}
188+
189+
// Create endpoint for crash output
190+
let endpoint = if output_url.is_empty() {
191+
None
192+
} else {
193+
Some(Endpoint::from_slice(&output_url))
194+
};
195+
196+
println!("Output endpoint: {:?}", endpoint.as_ref().map(|e| &e.url));
197+
198+
// Initialize Windows crashtracker
199+
let metadata = Metadata {
200+
library_name: "libdatadog".to_owned(),
201+
library_version: "1.0.0".to_owned(),
202+
family: "native".to_owned(),
203+
tags: vec![
204+
tag!("service", "foo"),
205+
tag!("service_version", "bar"),
206+
tag!("runtime-id", "xyz"),
207+
tag!("language", "native"),
208+
]
209+
.into_iter()
210+
.map(|x| x.to_string())
211+
.collect(),
212+
};
213+
214+
// Get current module path (this executable)
215+
let module_path = env::current_exe()?;
216+
let module_name = module_path.to_string_lossy().to_string();
217+
218+
println!("Initializing Windows crashtracker...");
219+
println!("Module: {}", module_name);
220+
println!("Endpoint: {:?}", endpoint);
221+
222+
// Initialize crashtracker
223+
init_crashtracking_windows(module_name, endpoint.as_ref(), metadata)?;
224+
225+
println!("Crashtracker initialized successfully!");
226+
227+
// Enable Windows Error Reporting like the FFI test app does
228+
println!("Enabling Windows Error Reporting...");
229+
unsafe {
230+
use windows::Win32::System::Diagnostics::Debug::{SetErrorMode, THREAD_ERROR_MODE};
231+
SetErrorMode(THREAD_ERROR_MODE(0x0001));
232+
}
233+
234+
// Add a longer delay to ensure WER registration is complete
235+
println!("Waiting for WER registration to complete...");
236+
std::thread::sleep(std::time::Duration::from_millis(500));
237+
238+
println!("About to trigger crash in call stack: main -> fn1 -> fn2 -> fn3");
239+
println!("This should generate an access violation that WER will catch...");
240+
241+
// Create the call stack for better crash traces
242+
fn1();
243+
244+
// This should never be reached
245+
println!("ERROR: Failed to crash!");
246+
Ok(())
247+
}
248+
}

0 commit comments

Comments
 (0)