-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Record the last fatal error message for crash reporting on Windows #72718
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
Conversation
nice! is there a good way to test this change as well? |
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.
Thanks, that'll be very helpful!
stdlib/public/runtime/Errors.cpp
Outdated
#if defined(_WIN32) | ||
// The last fatal error message is accessible for crash reporting on | ||
// Windows. | ||
char *oldMessage = nullptr; |
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 could reuse the same code as above by defining char** lastFatalErrorMessage =
&gCRAnnotations
or &gLastFatalErrorMessage
based on preprocessor values.
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.
Done
@@ -33,3 +33,10 @@ struct crashreporter_annotations_t gCRAnnotations __attribute__(( | |||
} | |||
|
|||
#endif | |||
|
|||
#if defined(_WIN32) |
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 the redeclaration necessary given #include "swift/Runtime/Debug.h"
?
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.
Yes, note that the one in Debug.h
is extern and this here is the real definition / storage location.
Added a test |
PTAL |
} | ||
let ppLastFatalErrorMessage = unsafeBitCast( | ||
GetProcAddress(hSwiftCore, "gLastFatalErrorMessage"), | ||
to: UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>.self) |
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 it possible to cast it to Optional<UnsafeMutablePointer<Optional<UnsafeMutablePointer<UInt8>>>>
instead? That way you can compare it for nil using optional instead of the bit pattern.
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.
Done, PTAL
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.
Thanks!
@swift-ci please smoke test |
@hjyamauchi Also, could you add a test case for |
Also consider: #72785 - this is currently Windows specific which seems like a shame. Additionally, I am concerned about the uniqueness of the address of the storage when used across modules on PE/COFF where the address of a global imported would be the IAT slot IIRC. |
@hjyamauchi here's an example of a try failure:
|
I'm a little conflicted about this. I think @compnerd is right that there's an issue with the global storage on Windows, but on a more general note I'm not sure how users are expected to make use of this (on non-Darwin platforms). What's really needed (IMO) is a Windows version of the crash handling code that I added for Darwin and Linux, and then a little bit of extra work to better integrate From a platform standpoint, on Windows it might actually make sense for |
Having a custom stream in the mini dump is another option on windows that we shouldn't rule out imo. That does require that we install a custom dump handler though. I'm hesitant to expose a stream writer as SPI as that would cause additional code execution in the address space after a fatalError. |
A way that I'm thinking of using this is through sentry/crashpad as in thebrowsercompany/swift-sentry#35 This works and puts the fatal error messages into sentry crash reports through a minidump.
Can you point to "the crash handling code that I added for Darwin and Linux", if available?
Do you mind clarifying "report things to the Event Log using |
That is a product level decision, not a language level. The only two "blessed" error reporting mechanisms for Windows would be the custom minidump writer and
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-reporteventw |
The Linux crash handler is here: CrashHandlerLinux.cpp. There's a similar one for macOS, and I've been meaning to get around to writing something for Windows too. It's on by default for Linux, and I was intending to have it on by default for Windows also, at least for console applications (subject to discussing it with @compnerd, since it does mean running code in a crashed process, which is all kinds of fun). |
Agreed. The existing Linux and macOS crash handlers both make sure to crash the process the same way it would have crashed without them. |
Closing this in favor of #72785 |
AFAICT,
crashreporter
is specific to Darwin and currently it's not possible to record the fatal error message in a crash dump on Windows. Use a similar technique to make it available for Windows crash dump tools.