[llvm-commits] [llvm] r109586 - in /llvm/trunk: include/llvm/Support/CrashRecoveryContext.h lib/Support/CrashRecoveryContext.cpp
Daniel Dunbar
daniel at zuster.org
Wed Jul 28 08:40:20 PDT 2010
Author: ddunbar
Date: Wed Jul 28 10:40:20 2010
New Revision: 109586
URL: http://llvm.org/viewvc/llvm-project?rev=109586&view=rev
Log:
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.
Added:
llvm/trunk/include/llvm/Support/CrashRecoveryContext.h
llvm/trunk/lib/Support/CrashRecoveryContext.cpp
Added: llvm/trunk/include/llvm/Support/CrashRecoveryContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CrashRecoveryContext.h?rev=109586&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Support/CrashRecoveryContext.h (added)
+++ llvm/trunk/include/llvm/Support/CrashRecoveryContext.h Wed Jul 28 10:40:20 2010
@@ -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
Added: llvm/trunk/lib/Support/CrashRecoveryContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CrashRecoveryContext.cpp?rev=109586&view=auto
==============================================================================
--- llvm/trunk/lib/Support/CrashRecoveryContext.cpp (added)
+++ llvm/trunk/lib/Support/CrashRecoveryContext.cpp Wed Jul 28 10:40:20 2010
@@ -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;
+}
More information about the llvm-commits
mailing list