forked from OSchip/llvm-project
[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
This commit is contained in:
parent
9a3740c339
commit
faace36508
|
@ -21,12 +21,20 @@
|
|||
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
|
||||
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
|
||||
|
||||
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
|
||||
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
|
||||
// RUN: not %clang %s @%t.rsp -DFATAL 2>&1 | FileCheck %s
|
||||
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
|
||||
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
|
||||
|
||||
// REQUIRES: crash-recovery
|
||||
|
||||
#ifdef PARSER
|
||||
#pragma clang __debug parser_crash
|
||||
#elif CRASH
|
||||
#pragma clang __debug crash
|
||||
#elif FATAL
|
||||
#pragma clang __debug llvm_fatal_error
|
||||
#endif
|
||||
|
||||
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
@ -69,7 +70,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
|
|||
// We cannot recover from llvm errors. When reporting a fatal error, exit
|
||||
// with status 70 to generate crash diagnostics. For BSD systems this is
|
||||
// defined as an internal software error. Otherwise, exit with status 1.
|
||||
exit(GenCrashDiag ? 70 : 1);
|
||||
llvm::sys::Process::Exit(GenCrashDiag ? 70 : 1);
|
||||
}
|
||||
|
||||
#ifdef CLANG_HAVE_RLIMITS
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
@ -555,7 +556,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message,
|
|||
Diags.Report(diag::err_fe_error_backend) << Message;
|
||||
|
||||
// We cannot recover from llvm errors.
|
||||
exit(1);
|
||||
sys::Process::Exit(1);
|
||||
}
|
||||
|
||||
int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
|
||||
|
|
|
@ -97,6 +97,11 @@ public:
|
|||
return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize);
|
||||
}
|
||||
|
||||
/// Explicitly trigger a crash recovery in the current process, and
|
||||
/// return failure from RunSafely(). This function does not return.
|
||||
LLVM_ATTRIBUTE_NORETURN
|
||||
void HandleExit(int RetCode);
|
||||
|
||||
/// In case of a crash, this is the crash identifier.
|
||||
int RetCode = 0;
|
||||
|
||||
|
|
|
@ -201,6 +201,12 @@ public:
|
|||
/// Get the result of a process wide random number generator. The
|
||||
/// generator will be automatically seeded in non-deterministic fashion.
|
||||
static unsigned GetRandomNumber();
|
||||
|
||||
/// Equivalent to ::exit(), except when running inside a CrashRecoveryContext.
|
||||
/// In that case, the control flow will resume after RunSafely(), like for a
|
||||
/// crash, rather than exiting the current process.
|
||||
LLVM_ATTRIBUTE_NORETURN
|
||||
static void Exit(int RetCode);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
#include "llvm/Support/ThreadLocal.h"
|
||||
#include <mutex>
|
||||
#include <setjmp.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> // for GetExceptionInformation
|
||||
#endif
|
||||
#if LLVM_ON_UNIX
|
||||
#include <sysexits.h> // EX_IOERR
|
||||
#endif
|
||||
|
@ -178,6 +175,9 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
|
|||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#include <windows.h> // for GetExceptionInformation
|
||||
|
||||
// If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way
|
||||
// better than VEH. Vectored exception handling catches all exceptions happening
|
||||
// on the thread with installed exception handlers, so it can interfere with
|
||||
|
@ -203,6 +203,8 @@ static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
|
|||
}
|
||||
|
||||
int RetCode = (int)Except->ExceptionRecord->ExceptionCode;
|
||||
if ((RetCode & 0xF0000000) == 0xE0000000)
|
||||
RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
|
||||
|
||||
// Handle the crash
|
||||
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
|
||||
|
@ -280,10 +282,13 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
|
|||
// TODO: We can capture the stack backtrace here and store it on the
|
||||
// implementation if we so choose.
|
||||
|
||||
int RetCode = (int)ExceptionInfo->ExceptionRecord->ExceptionCode;
|
||||
if ((RetCode & 0xF0000000) == 0xE0000000)
|
||||
RetCode &= ~0xF0000000; // this crash was generated by sys::Process::Exit
|
||||
|
||||
// Handle the crash
|
||||
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
|
||||
(int)ExceptionInfo->ExceptionRecord->ExceptionCode,
|
||||
reinterpret_cast<uintptr_t>(ExceptionInfo));
|
||||
RetCode, reinterpret_cast<uintptr_t>(ExceptionInfo));
|
||||
|
||||
// Note that we don't actually get here because HandleCrash calls
|
||||
// longjmp, which means the HandleCrash function never returns.
|
||||
|
@ -416,6 +421,21 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
|
|||
|
||||
#endif // !_MSC_VER
|
||||
|
||||
LLVM_ATTRIBUTE_NORETURN
|
||||
void CrashRecoveryContext::HandleExit(int RetCode) {
|
||||
#if defined(_WIN32)
|
||||
// SEH and VEH
|
||||
::RaiseException(0xE0000000 | RetCode, 0, 0, NULL);
|
||||
#else
|
||||
// On Unix we don't need to raise an exception, we go directly to
|
||||
// HandleCrash(), then longjmp will unwind the stack for us.
|
||||
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *)Impl;
|
||||
assert(CRCI && "Crash recovery context never initialized!");
|
||||
CRCI->HandleCrash(RetCode, 0 /*no sig num*/);
|
||||
#endif
|
||||
llvm_unreachable("Most likely setjmp wasn't called!");
|
||||
}
|
||||
|
||||
// FIXME: Portability.
|
||||
static void setThreadBackgroundPriority() {
|
||||
#ifdef __APPLE__
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
#include "llvm/Support/WindowsError.h"
|
||||
|
@ -122,7 +123,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
|
|||
// files registered with RemoveFileOnSignal.
|
||||
sys::RunInterruptHandlers();
|
||||
|
||||
exit(1);
|
||||
sys::Process::Exit(1);
|
||||
}
|
||||
|
||||
void llvm::install_bad_alloc_error_handler(fatal_error_handler_t handler,
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Support/CrashRecoveryContext.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
|
@ -88,6 +89,13 @@ static bool coreFilesPrevented = !LLVM_ENABLE_CRASH_DUMPS;
|
|||
|
||||
bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; }
|
||||
|
||||
LLVM_ATTRIBUTE_NORETURN
|
||||
void Process::Exit(int RetCode) {
|
||||
if (CrashRecoveryContext *CRC = CrashRecoveryContext::GetCurrent())
|
||||
CRC->HandleExit(RetCode);
|
||||
::exit(RetCode);
|
||||
}
|
||||
|
||||
// Include the platform-specific parts of this class.
|
||||
#ifdef LLVM_ON_UNIX
|
||||
#include "Unix/Process.inc"
|
||||
|
|
Loading…
Reference in New Issue