mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-08 03:30:22 +00:00
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
This commit is contained in:
parent
5d4b32ef96
commit
a309dac868
82
include/llvm/Support/CrashRecoveryContext.h
Normal file
82
include/llvm/Support/CrashRecoveryContext.h
Normal file
@ -0,0 +1,82 @@
|
||||
//===--- CrashRecoveryContext.h - Crash Recovery ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
|
||||
#define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
|
||||
/// \brief Crash recovery helper object.
|
||||
///
|
||||
/// This class implements support for running operations in a safe context so
|
||||
/// that crashes (memory errors, stack overflow, assertion violations) can be
|
||||
/// detected and control restored to the crashing thread. Crash detection is
|
||||
/// purely "best effort", the exact set of failures which can be recovered from
|
||||
/// is platform dependent.
|
||||
///
|
||||
/// Clients make use of this code by first calling
|
||||
/// CrashRecoveryContext::Enable(), and then executing unsafe operations via a
|
||||
/// CrashRecoveryContext object. For example:
|
||||
///
|
||||
/// void actual_work(void *);
|
||||
///
|
||||
/// void foo() {
|
||||
/// CrashRecoveryContext CRC;
|
||||
///
|
||||
/// if (!CRC.RunSafely(actual_work, 0)) {
|
||||
/// ... a crash was detected, report error to user ...
|
||||
/// }
|
||||
///
|
||||
/// ... no crash was detected ...
|
||||
/// }
|
||||
///
|
||||
/// Crash recovery contexts may not be nested.
|
||||
class CrashRecoveryContext {
|
||||
void *Impl;
|
||||
|
||||
public:
|
||||
CrashRecoveryContext() : Impl(0) {}
|
||||
~CrashRecoveryContext();
|
||||
|
||||
/// \brief Enable crash recovery. This function is not thread safe, clients
|
||||
/// should call it during startup or with a lock held.
|
||||
static void Enable();
|
||||
|
||||
/// \brief Disable crash recovery. This function is not thread safe, clients
|
||||
/// should call it during startup or with a lock held.
|
||||
static void Disable();
|
||||
|
||||
/// \brief Execute the provide callback function (with the given arguments) in
|
||||
/// a protected context.
|
||||
///
|
||||
/// \return True if the function completed successfully, and false if the
|
||||
/// function crashed (or HandleCrash was called explicitly). Clients should
|
||||
/// make as little assumptions as possible about the program state when
|
||||
/// RunSafely has returned false. Clients can use getBacktrace() to retrieve
|
||||
/// the backtrace of the crash on failures.
|
||||
bool RunSafely(void (*Fn)(void*), void *UserData);
|
||||
|
||||
/// \brief Explicitly trigger a crash recovery in the current process, and
|
||||
/// return failure from RunSafely(). This function does not return.
|
||||
void HandleCrash();
|
||||
|
||||
/// \brief Return a string containing the backtrace where the crash was
|
||||
/// detected; or empty if the backtrace wasn't recovered.
|
||||
///
|
||||
/// This function is only valid when a crash has been detected (i.e.,
|
||||
/// RunSafely() has returned false.
|
||||
const std::string &getBacktrace() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
88
lib/Support/CrashRecoveryContext.cpp
Normal file
88
lib/Support/CrashRecoveryContext.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
//===--- 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user