summaryrefslogtreecommitdiffstats
path: root/lib/Support/CrashRecoveryContext.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-07-28 15:40:20 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-07-28 15:40:20 +0000
commita309dac868e591d7254f570b950a50f640c009f8 (patch)
tree047f97004bb6e2c94dbdc7cbdd934bce30f670a2 /lib/Support/CrashRecoveryContext.cpp
parent5d4b32ef96ef91026517ea1769faa7066467d0a9 (diff)
downloadexternal_llvm-a309dac868e591d7254f570b950a50f640c009f8.zip
external_llvm-a309dac868e591d7254f570b950a50f640c009f8.tar.gz
external_llvm-a309dac868e591d7254f570b950a50f640c009f8.tar.bz2
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
Diffstat (limited to 'lib/Support/CrashRecoveryContext.cpp')
-rw-r--r--lib/Support/CrashRecoveryContext.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp
new file mode 100644
index 0000000..870221e
--- /dev/null
+++ b/lib/Support/CrashRecoveryContext.cpp
@@ -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;
+}