-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crashtracking for Windows #892
base: main
Are you sure you want to change the base?
Conversation
BenchmarksComparisonBenchmark execution time: 2025-02-21 10:18:46 Comparing candidate commit af91be6 in PR branch Found 2 performance improvements and 0 performance regressions! Performance is the same for 50 metrics, 2 unstable metrics. scenario:credit_card/is_card_number/378282246310005
CandidateCandidate benchmark detailsGroup 1
Group 2
Group 3
Group 4
Group 5
Group 6
Group 7
Group 8
Group 9
Group 10
Group 11
Group 12
Group 13
BaselineOmitted due to size. |
aa6bc16
to
14136df
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #892 +/- ##
==========================================
+ Coverage 71.77% 71.82% +0.04%
==========================================
Files 328 328
Lines 48577 48577
==========================================
+ Hits 34866 34888 +22
+ Misses 13711 13689 -22
|
use std::ptr::{addr_of, read_unaligned}; | ||
use windows::core::{w, HRESULT, PCWSTR}; | ||
use windows::Win32::Foundation::{BOOL, ERROR_SUCCESS, E_FAIL, HANDLE, HMODULE, S_OK, TRUE}; | ||
#[cfg(target_arch = "x86_64")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to consider ARM?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the future maybe, but for now ARM on Windows Server is not a thing (only the desktop version of Windows runs on ARM)
let mut path = env::temp_dir().join(process_name); | ||
path.set_extension("dll"); | ||
|
||
// Attempt to move it just in case it already exists |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would this happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we log something here? Is this unexpected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reused the logic from the trampoline (since the need is the same): https://github.com/DataDog/libdatadog/blob/main/spawn_worker/src/win32.rs#L48
The filename is made of the user SID and the version number, so if multiple instances of PHP are running they will share the same file. I think this is a good thing for crashtracking because we need to add the path to the registry, and I'm afraid we would add a lot of garbage if the path was random.
@@ -38,4 +38,17 @@ fn main() { | |||
.try_compile_shared_lib("ld_preload_trampoline.shared_lib") | |||
.unwrap(); | |||
} | |||
|
|||
if cfg!(target_os = "windows") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to use this rather than just statically #[cfg...]
?
.file("src/crashtracking_trampoline.cpp") // Path to your C++ file | ||
.warnings(true) | ||
.warnings_into_errors(true) | ||
.flag("/std:c++17") // Set the C++ standard (adjust as needed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does having a C++
binary increase the size of libdatadog vs C
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably but the size is still reasonable. The only reason I used C++ is because it has regex support in the stdlib. The DLL size is 160 KB, I believe it's acceptable (it was ~60 KB in C with manual parsing).
|
||
if (!EnumProcessModules(process, nullptr, 0, &cbNeeded)) | ||
{ | ||
OutputDebugStringW(L"Failed to enumerate process modules (1st)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does 1st vs 2nd mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We call EnumProcessModules
twice (first to get the number of modules, then to populate them). It's simply to know if we failed in the first or the second call.
Some(&mut bytes_read), | ||
); | ||
|
||
if result.is_err() || bytes_read != size { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
anyhow::ensure
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!( | ||
f, | ||
"{:08x}{:04x}{:04x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this documented somewhere?
let debug_data_dir: IMAGE_DATA_DIRECTORY = if is_pe32 { | ||
let nt_headers32: IMAGE_NT_HEADERS32 = read_memory(process_handle, nt_headers_address)?; | ||
nt_headers32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG.0 as usize] | ||
} else { | ||
let nt_headers64: IMAGE_NT_HEADERS64 = read_memory(process_handle, nt_headers_address)?; | ||
nt_headers64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG.0 as usize] | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there documentation for why this is the case?
} | ||
} | ||
|
||
Err(anyhow!("No CodeView entry found")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
anyhow::bail!
if thread_entry.th32OwnerProcessID == pid { | ||
thread_ids.push(thread_entry.th32ThreadID); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We loop over every thread on the machine? Could that be expensive?
What does this PR do?
A brief description of the change being made with this pull request.
Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
How to test the change?
Describe here in detail how the change can be validated.