[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