Skip to content

Commit a6b2669

Browse files
committed
Record the last fatal error message for crash reporting on Windows
1 parent 311c55f commit a6b2669

File tree

4 files changed

+80
-8
lines changed

4 files changed

+80
-8
lines changed

include/swift/Runtime/Debug.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ static inline const char *CRGetCrashLogMessage() {
6060
SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE
6161
static inline void CRSetCrashLogMessage(const char *) {}
6262

63+
#if defined(_WIN32)
64+
extern "C" {
65+
SWIFT_ATTRIBUTE_FOR_EXPORTS
66+
extern char* gLastFatalErrorMessage;
67+
}
68+
#endif // _WIN32
69+
6370
#endif
6471

6572
namespace swift {

stdlib/public/runtime/CrashReporter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,10 @@ struct crashreporter_annotations_t gCRAnnotations __attribute__((
3333
}
3434

3535
#endif
36+
37+
#if defined(_WIN32)
38+
extern "C" {
39+
SWIFT_ATTRIBUTE_FOR_EXPORTS
40+
char* gLastFatalErrorMessage = nullptr;
41+
}
42+
#endif

stdlib/public/runtime/Errors.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
#include "swift/Runtime/Atomic.h"
7171
#endif // SWIFT_HAVE_CRASHREPORTERCLIENT
7272

73+
#if defined(_WIN32)
74+
#include "swift/Runtime/Atomic.h"
75+
#endif // _WIN32
76+
7377
#include "BacktracePrivate.h"
7478

7579
namespace FatalErrorFlags {
@@ -268,16 +272,15 @@ void swift::printCurrentBacktrace(unsigned framesToSkip) {
268272
fprintf(stderr, "<backtrace unavailable>\n");
269273
}
270274

271-
// Report a message to any forthcoming crash log.
272-
static void
273-
reportOnCrash(uint32_t flags, const char *message)
274-
{
275-
#ifdef SWIFT_HAVE_CRASHREPORTERCLIENT
275+
#if defined(SWIFT_HAVE_CRASHREPORTERCLIENT) || defined(_WIN32)
276+
// Update the last fatal error message for crash reporting.
277+
static void updateLastFatalErrorMessage(void* location,
278+
const char* message) {
276279
char *oldMessage = nullptr;
277280
char *newMessage = nullptr;
278281

279282
oldMessage = std::atomic_load_explicit(
280-
(volatile std::atomic<char *> *)&gCRAnnotations.message,
283+
(volatile std::atomic<char *> *)location,
281284
SWIFT_MEMORY_ORDER_CONSUME);
282285

283286
do {
@@ -292,13 +295,25 @@ reportOnCrash(uint32_t flags, const char *message)
292295
newMessage = strdup(message);
293296
}
294297
} while (!std::atomic_compare_exchange_strong_explicit(
295-
(volatile std::atomic<char *> *)&gCRAnnotations.message,
298+
(volatile std::atomic<char *> *)location,
296299
&oldMessage, newMessage,
297300
std::memory_order_release,
298301
SWIFT_MEMORY_ORDER_CONSUME));
302+
}
303+
#endif // SWIFT_HAVE_CRASHREPORTERCLIENT || _WIN32
304+
305+
// Report a message to any forthcoming crash log.
306+
static void
307+
reportOnCrash(uint32_t flags, const char *message)
308+
{
309+
#ifdef SWIFT_HAVE_CRASHREPORTERCLIENT
310+
updateLastFatalErrorMessage(&gCRAnnotations.message, message);
311+
#elif defined(_WIN32)
312+
// Make the fatal error message accessible for Windows dump tools.
313+
updateLastFatalErrorMessage(&gLastFatalErrorMessage, message);
299314
#else
300315
// empty
301-
#endif // SWIFT_HAVE_CRASHREPORTERCLIENT
316+
#endif // SWIFT_HAVE_CRASHREPORTERCLIENT || _WIN32
302317
}
303318

304319
// Report a message to system console and stderr.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift %s -o %t/a.out
3+
// RUN: %target-codesign %t/a.out
4+
// RUN: not %target-run %t/a.out 2>&1 | %FileCheck %s
5+
// REQUIRES: executable_test
6+
// REQUIRES: OS=windows-msvc
7+
8+
// CHECK: Fatal error message: a/fatal-message-crash-dump-win.swift:{{[0-9]+}}: Fatal error: Fatal crash!
9+
10+
import WinSDK
11+
12+
func crash() {
13+
fatalError("Fatal crash!")
14+
}
15+
16+
func setupHandler() {
17+
SetUnhandledExceptionFilter { exception_pointers in
18+
guard let hSwiftCore = GetModuleHandleA("swiftCore.dll") else {
19+
return EXCEPTION_EXECUTE_HANDLER
20+
}
21+
let ppLastFatalErrorMessage = unsafeBitCast(
22+
GetProcAddress(hSwiftCore, "gLastFatalErrorMessage"),
23+
to: UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>.self)
24+
if ppLastFatalErrorMessage == UnsafeMutablePointer<UnsafeMutablePointer<UInt8>>(bitPattern: 0) {
25+
return EXCEPTION_EXECUTE_HANDLER
26+
}
27+
let pLastFatalErrorMessage = ppLastFatalErrorMessage.pointee;
28+
if pLastFatalErrorMessage == UnsafeMutablePointer<UInt8>(bitPattern: 0) {
29+
return EXCEPTION_EXECUTE_HANDLER
30+
}
31+
let message = "Fatal error message: \(String(cString: pLastFatalErrorMessage))"
32+
message.utf8CString.withUnsafeBufferPointer { buf in
33+
let addr = buf.baseAddress!
34+
let count = DWORD(buf.count)
35+
let stderr = GetStdHandle(STD_ERROR_HANDLE)
36+
WriteFile(stderr, addr, count, nil, nil)
37+
}
38+
return EXCEPTION_EXECUTE_HANDLER
39+
}
40+
}
41+
42+
setupHandler()
43+
crash()

0 commit comments

Comments
 (0)