llvm-6502/lib/Support/CrashRecoveryContext.cpp
Daniel Dunbar a309dac868 Support: Add CrashRecoveryContext helper object.
- Designed as a simple wrapper to allow clients to attempt to catch crashes
   (memory errors, assertion violations, etc.) and do some kind of recovery.

 - Currently doesn't actually attempt to catch crashes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@109586 91177308-0d34-0410-b5e6-96231b3b80d8
2010-07-28 15:40:20 +00:00

89 lines
2.2 KiB
C++

//===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/ADT/SmallString.h"
#include <setjmp.h>
using namespace llvm;
namespace {
struct CrashRecoveryContextImpl;
struct CrashRecoveryContextImpl {
std::string Backtrace;
::jmp_buf JumpBuffer;
volatile unsigned Failed : 1;
public:
CrashRecoveryContextImpl() : Failed(false) {}
void HandleCrash() {
assert(!Failed && "Crash recovery context already failed!");
Failed = true;
// FIXME: Stash the backtrace.
// Jump back to the RunSafely we were called under.
longjmp(JumpBuffer, 1);
}
};
}
static bool gCrashRecoveryEnabled = false;
CrashRecoveryContext::~CrashRecoveryContext() {
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
delete CRCI;
}
void CrashRecoveryContext::Enable() {
if (gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = true;
}
void CrashRecoveryContext::Disable() {
if (!gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = false;
}
bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) {
// If crash recovery is disabled, do nothing.
if (gCrashRecoveryEnabled) {
assert(!Impl && "Crash recovery context already initialized!");
CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl;
Impl = CRCI;
if (setjmp(CRCI->JumpBuffer) != 0) {
return false;
}
}
Fn(UserData);
return true;
}
void CrashRecoveryContext::HandleCrash() {
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;
assert(CRCI && "Crash recovery context never initialized!");
CRCI->HandleCrash();
}
const std::string &CrashRecoveryContext::getBacktrace() const {
CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl;
assert(CRC && "Crash recovery context never initialized!");
assert(CRC->Failed && "No crash was detected!");
return CRC->Backtrace;
}