[DNM] Add windows logging to find the source of 0xDEAD - #4062
[DNM] Add windows logging to find the source of 0xDEAD#4062smalis-msft wants to merge 5 commits into
Conversation
|
This PR modifies files containing For more on why we check whole files, instead of just diffs, check out the Rustonomicon |
There was a problem hiding this comment.
Pull request overview
This PR adds Windows-specific unhandled SEH exception logging so that unexpected process terminations (previously only visible as an exit code) emit minimal diagnostics to stderr, improving debuggability of rare crash scenarios (e.g., issue #71).
Changes:
- Add
pal::windows::log_unhandled_exceptions()that installs a top-level exception filter and writes exception code/address/thread-id to stderr viaWriteFile. - Call the new logging setup from
openvmm_entry::do_main()alongside the existingdisable_hard_error_dialog()Windows setup.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| support/pal/src/windows.rs | Adds the unhandled exception filter implementation and low-level stderr write. |
| openvmm/openvmm_entry/src/lib.rs | Installs the exception filter early in Windows startup so it applies to the process lifetime. |
|
I don't think this is a good idea. If there's an unhandled exception then want to stop running code in the process ASAP to minimize the possibility of it turning into an EOP. If we want to get more information about crashes in CI, we should configure the system to save crash dumps. |
|
I've tried to configure crash dumps in CI before without much success. Maybe I'll just let this spin in CI a few times to see if it catches anything. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
support/pal/src/windows.rs:1248
log_unexpected_exceptions()registers a vectored exception handler every time it’s called, which can lead to duplicate logging (and extra overhead) if it’s invoked more than once in-process. Consider guarding the registration withOnceso the function is idempotent.
// SAFETY: This Win32 API has no safety requirements.
unsafe {
AddVectoredExceptionHandler(1, Some(handler));
}
support/pal/src/windows.rs:1189
- The doc comment says “any configured error reporting still runs”, but
SetUnhandledExceptionFilterreplaces any previously-installed top-level exception filter. That can change crash-reporting behavior for code that had already registered its own filter; consider clarifying this in the docs (or chaining to the previous filter if that’s intended).
/// The filter returns `EXCEPTION_CONTINUE_SEARCH`, so the process still dies
/// exactly as it would have, with the same exit code, and any configured error
/// reporting still runs.
support/pal/src/windows.rs:1206
log_unhandled_exceptions()installs a process-global unhandled-exception filter every time it’s called. Since re-installing (and potentially overwriting) global handlers is easy to do accidentally, it’s safer to make this initialization idempotent viaOnce.
This issue also appears on line 1245 of the same file.
// SAFETY: This Win32 API has no safety requirements.
unsafe {
SetUnhandledExceptionFilter(Some(filter));
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
support/pal/src/windows.rs:1291
- The
WriteFilecall passes a*const u8(out.buf.as_ptr()) where the Win32 binding expects*const c_void. OtherWriteFilecall sites in the repo use.cast()for this. As written, this is likely a type mismatch that won’t compile (or is inconsistent with the expected signature).
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
out.buf.as_ptr(),
out.len as u32,
petri/src/vm/hyperv/powershell.rs:1732
host_failure_eventsqueriesApplicationandSystemwith only aStartTimefilter and no upper bound. On long-running tests (or chatty hosts), this can produce extremely large outputs and slow post-test hook execution, and Petri currently does not enforce any log size limits. Consider truncating the collected list to a reasonable maximum (keeping the most recent events) to avoid ballooning CI artifacts/timeouts.
/// Get the host event log entries written since `start_time` that could
/// explain a VMM process disappearing without leaving anything in its own
/// logs, such as a fault report or a hypervisor error.
pub async fn host_failure_events(start_time: &Timestamp) -> Vec<WinEvent> {
let mut events = Vec::new();
// Query each channel separately so that one missing or inaccessible
// channel does not suppress the rest.
for table in [
APPLICATION_TABLE,
SYSTEM_TABLE,
HYPERV_HYPERVISOR_TABLE,
HYPERV_WORKER_TABLE,
HYPERV_VMMS_TABLE,
] {
match run_get_winevent(&[table], Some(start_time), None, &[]).await {
Ok(e) => events.extend(e),
Err(err) => tracing::warn!(
table,
error = err.as_ref() as &dyn std::error::Error,
"failed to read host event log"
),
}
}
events.sort_by_key(|e| e.time_created);
events
}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
support/pal/src/windows.rs:1294
WriteFileexpects a*const c_voidbuffer pointer; passingout.buf.as_ptr()without a cast doesn’t match how other Win32 calls in the repo are written and can fail to compile depending on thewindows-syssignature. Cast the pointer toc_void(e.g. via.cast()).
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
out.buf.as_ptr(),
out.len as u32,
&mut written,
null_mut(),
);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
support/pal/src/windows.rs:1248
log_unexpected_exceptions()installs a new vectored handler every time it’s called and ignoresAddVectoredExceptionHandlerfailure (null return). Since this is a public helper, accidental double-installation can cause duplicate logging and makes diagnostics unreliable if the install fails silently. Consider guarding withOnceand asserting (or otherwise surfacing) install failure.
// SAFETY: This Win32 API has no safety requirements.
unsafe {
AddVectoredExceptionHandler(1, Some(handler));
}
Adding logging and rerunning CI repeatedly to figure out the source of #71.