Skip to content

Commit fd04cb4

Browse files
aganeazmodem
authored andcommitted
[Clang][Driver] After default -fintegrated-cc1, make llvm::report_fatal_error() generate preprocessed source + reproducer.sh again.
Added a test for #pragma clang __debug llvm_fatal_error to test for the original issue. Added llvm::sys::Process::Exit() and replaced ::exit() in places where it was appropriate. This new function would call the current CrashRecoveryContext if one is running on the same thread; or call ::exit() otherwise. Fixes PR44705. Differential Revision: https://reviews.llvm.org/D73742 (cherry picked from commit faace36)
1 parent aeba7ba commit fd04cb4

File tree

8 files changed

+59
-9
lines changed

8 files changed

+59
-9
lines changed

clang/test/Driver/crash-report.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,20 @@
2121
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
2222
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
2323

24+
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
25+
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
26+
// RUN: not %clang %s @%t.rsp -DFATAL 2>&1 | FileCheck %s
27+
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
28+
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
29+
2430
// REQUIRES: crash-recovery
2531

2632
#ifdef PARSER
2733
#pragma clang __debug parser_crash
2834
#elif CRASH
2935
#pragma clang __debug crash
36+
#elif FATAL
37+
#pragma clang __debug llvm_fatal_error
3038
#endif
3139

3240
// CHECK: Preprocessed source(s) and associated run script(s) are located at:

clang/tools/driver/cc1_main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "llvm/Support/ErrorHandling.h"
3737
#include "llvm/Support/ManagedStatic.h"
3838
#include "llvm/Support/Path.h"
39+
#include "llvm/Support/Process.h"
3940
#include "llvm/Support/Signals.h"
4041
#include "llvm/Support/TargetRegistry.h"
4142
#include "llvm/Support/TargetSelect.h"
@@ -69,7 +70,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
6970
// We cannot recover from llvm errors. When reporting a fatal error, exit
7071
// with status 70 to generate crash diagnostics. For BSD systems this is
7172
// defined as an internal software error. Otherwise, exit with status 1.
72-
exit(GenCrashDiag ? 70 : 1);
73+
llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);
7374
}
7475

7576
#ifdef CLANG_HAVE_RLIMITS

clang/tools/driver/cc1as_main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "llvm/Support/Host.h"
4747
#include "llvm/Support/MemoryBuffer.h"
4848
#include "llvm/Support/Path.h"
49+
#include "llvm/Support/Process.h"
4950
#include "llvm/Support/Signals.h"
5051
#include "llvm/Support/SourceMgr.h"
5152
#include "llvm/Support/TargetRegistry.h"
@@ -547,7 +548,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
547548
Diags.Report(diag::err_fe_error_backend) << Message;
548549

549550
// We cannot recover from llvm errors.
550-
exit(1);
551+
sys::Process::Exit(1);
551552
}
552553

553554
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {

llvm/include/llvm/Support/CrashRecoveryContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ class CrashRecoveryContext {
9797
return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize);
9898
}
9999

100+
/// Explicitly trigger a crash recovery in the current process, and
101+
/// return failure from RunSafely(). This function does not return.
102+
LLVM_ATTRIBUTE_NORETURN
103+
void HandleExit(int RetCode);
104+
100105
/// In case of a crash, this is the crash identifier.
101106
int RetCode = 0;
102107

llvm/include/llvm/Support/Process.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ class Process {
201201
/// Get the result of a process wide random number generator. The
202202
/// generator will be automatically seeded in non-deterministic fashion.
203203
static unsigned GetRandomNumber();
204+
205+
/// Equivalent to ::exit(), except when running inside a CrashRecoveryContext.
206+
/// In that case, the control flow will resume after RunSafely(), like for a
207+
/// crash, rather than exiting the current process.
208+
LLVM_ATTRIBUTE_NORETURN
209+
static void Exit(int RetCode);
204210
};
205211

206212
}

llvm/lib/Support/CrashRecoveryContext.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
#include "llvm/Support/ThreadLocal.h"
1515
#include <mutex>
1616
#include <setjmp.h>
17-
#ifdef _WIN32
18-
#include <windows.h> // for GetExceptionInformation
19-
#endif
2017
#if LLVM_ON_UNIX
2118
#include <sysexits.h> // EX_IOERR
2219
#endif
@@ -178,6 +175,9 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
178175
}
179176

180177
#if defined(_MSC_VER)
178+
179+
#include <windows.h> // for GetExceptionInformation
180+
181181
// If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way
182182
// better than VEH. Vectored exception handling catches all exceptions happening
183183
// on the thread with installed exception handlers, so it can interfere with
@@ -203,6 +203,8 @@ static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
203203
}
204204

205205
int RetCode = (int)Except->ExceptionRecord->ExceptionCode;
206+
if ((RetCode & 0xF0000000) == 0xE0000000)
207+
RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
206208

207209
// Handle the crash
208210
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
@@ -280,10 +282,13 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
280282
// TODO: We can capture the stack backtrace here and store it on the
281283
// implementation if we so choose.
282284

285+
int RetCode = (int)ExceptionInfo->ExceptionRecord->ExceptionCode;
286+
if ((RetCode & 0xF0000000) == 0xE0000000)
287+
RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
288+
283289
// Handle the crash
284290
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
285-
(int)ExceptionInfo->ExceptionRecord->ExceptionCode,
286-
reinterpret_cast<uintptr_t>(ExceptionInfo));
291+
RetCode, reinterpret_cast<uintptr_t>(ExceptionInfo));
287292

288293
// Note that we don't actually get here because HandleCrash calls
289294
// longjmp, which means the HandleCrash function never returns.
@@ -416,6 +421,21 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
416421

417422
#endif // !_MSC_VER
418423

424+
LLVM_ATTRIBUTE_NORETURN
425+
void CrashRecoveryContext::HandleExit(int RetCode) {
426+
#if defined(_WIN32)
427+
// SEH and VEH
428+
::RaiseException(0xE0000000 | RetCode, 0, 0, NULL);
429+
#else
430+
// On Unix we don't need to raise an exception, we go directly to
431+
// HandleCrash(), then longjmp will unwind the stack for us.
432+
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *)Impl;
433+
assert(CRCI && "Crash recovery context never initialized!");
434+
CRCI->HandleCrash(RetCode, 0 /*no sig num*/);
435+
#endif
436+
llvm_unreachable("Most likely setjmp wasn't called!");
437+
}
438+
419439
// FIXME: Portability.
420440
static void setThreadBackgroundPriority() {
421441
#ifdef __APPLE__

llvm/lib/Support/ErrorHandling.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/Support/Debug.h"
2020
#include "llvm/Support/Errc.h"
2121
#include "llvm/Support/Error.h"
22+
#include "llvm/Support/Process.h"
2223
#include "llvm/Support/Signals.h"
2324
#include "llvm/Support/Threading.h"
2425
#include "llvm/Support/WindowsError.h"
@@ -122,7 +123,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
122123
// files registered with RemoveFileOnSignal.
123124
sys::RunInterruptHandlers();
124125

125-
exit(1);
126+
sys::Process::Exit(1);
126127
}
127128

128129
void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,

llvm/lib/Support/Process.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
#include "llvm/Support/Process.h"
1414
#include "llvm/ADT/STLExtras.h"
1515
#include "llvm/ADT/StringExtras.h"
16-
#include "llvm/Config/llvm-config.h"
1716
#include "llvm/Config/config.h"
17+
#include "llvm/Config/llvm-config.h"
18+
#include "llvm/Support/CrashRecoveryContext.h"
1819
#include "llvm/Support/FileSystem.h"
1920
#include "llvm/Support/Path.h"
2021
#include "llvm/Support/Program.h"
@@ -88,6 +89,13 @@ static bool coreFilesPrevented = !LLVM_ENABLE_CRASH_DUMPS;
8889

8990
bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; }
9091

92+
LLVM_ATTRIBUTE_NORETURN
93+
void Process::Exit(int RetCode) {
94+
if (CrashRecoveryContext *CRC = CrashRecoveryContext::GetCurrent())
95+
CRC->HandleExit(RetCode);
96+
::exit(RetCode);
97+
}
98+
9199
// Include the platform-specific parts of this class.
92100
#ifdef LLVM_ON_UNIX
93101
#include "Unix/Process.inc"

0 commit comments

Comments
 (0)