summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Support/CrashRecoveryTest.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2017-05-17 17:02:16 +0000
committerReid Kleckner <rnk@google.com>2017-05-17 17:02:16 +0000
commit91fea018ee81a50483817c2d19f7c7074a6082ab (patch)
tree2973abe9c61b3ef4990dd5a55054abf717dcf8c3 /llvm/unittests/Support/CrashRecoveryTest.cpp
parent4035ec59bf30bedce65ad8a6f81f966944654ac1 (diff)
downloadbcm5719-llvm-91fea018ee81a50483817c2d19f7c7074a6082ab.tar.gz
bcm5719-llvm-91fea018ee81a50483817c2d19f7c7074a6082ab.zip
[CrashRecovery] Use SEH __try instead of VEH when available
Summary: It avoids problems when other libraries raise exceptions. In particular, OutputDebugString raises an exception that the debugger is supposed to catch and suppress. VEH kicks in first right now, and that is entirely incorrect. Unfortunately, GCC does not support SEH, so I've kept the old buggy VEH codepath around. We could fix it with SetUnhandledExceptionFilter, but that is not per-thread, so a well-behaved library shouldn't set it. Reviewers: zturner Subscribers: llvm-commits, mgorny Differential Revision: https://reviews.llvm.org/D33261 llvm-svn: 303274
Diffstat (limited to 'llvm/unittests/Support/CrashRecoveryTest.cpp')
-rw-r--r--llvm/unittests/Support/CrashRecoveryTest.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/llvm/unittests/Support/CrashRecoveryTest.cpp b/llvm/unittests/Support/CrashRecoveryTest.cpp
new file mode 100644
index 00000000000..dbb0db57679
--- /dev/null
+++ b/llvm/unittests/Support/CrashRecoveryTest.cpp
@@ -0,0 +1,83 @@
+//===- llvm/unittest/Support/CrashRecoveryTest.cpp ------------------------===//
+//
+// 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/Support/Compiler.h"
+#include "gtest/gtest.h"
+
+#ifdef LLVM_ON_WIN32
+#define WIN32_LEAN_AND_MEAN
+#define NOGDI
+#include <windows.h>
+#endif
+
+using namespace llvm;
+using namespace llvm::sys;
+
+static int GlobalInt = 0;
+static void nullDeref() { *(volatile int *)nullptr = 0; }
+static void incrementGlobal() { ++GlobalInt; }
+static void llvmTrap() { LLVM_BUILTIN_TRAP; }
+
+TEST(CrashRecoveryTest, Basic) {
+ llvm::CrashRecoveryContext::Enable();
+ GlobalInt = 0;
+ EXPECT_TRUE(CrashRecoveryContext().RunSafely(incrementGlobal));
+ EXPECT_EQ(1, GlobalInt);
+ EXPECT_FALSE(CrashRecoveryContext().RunSafely(nullDeref));
+ EXPECT_FALSE(CrashRecoveryContext().RunSafely(llvmTrap));
+}
+
+struct IncrementGlobalCleanup : CrashRecoveryContextCleanup {
+ IncrementGlobalCleanup(CrashRecoveryContext *CRC)
+ : CrashRecoveryContextCleanup(CRC) {}
+ virtual void recoverResources() { ++GlobalInt; }
+};
+
+static void noop() {}
+
+TEST(CrashRecoveryTest, Cleanup) {
+ llvm::CrashRecoveryContext::Enable();
+ GlobalInt = 0;
+ {
+ CrashRecoveryContext CRC;
+ CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));
+ EXPECT_TRUE(CRC.RunSafely(noop));
+ } // run cleanups
+ EXPECT_EQ(1, GlobalInt);
+
+ GlobalInt = 0;
+ {
+ CrashRecoveryContext CRC;
+ CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));
+ EXPECT_FALSE(CRC.RunSafely(nullDeref));
+ } // run cleanups
+ EXPECT_EQ(1, GlobalInt);
+}
+
+#ifdef LLVM_ON_WIN32
+static void raiseIt() {
+ RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL);
+}
+
+TEST(CrashRecoveryTest, RaiseException) {
+ llvm::CrashRecoveryContext::Enable();
+ EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt));
+}
+
+static void outputString() {
+ OutputDebugStringA("output for debugger\n");
+}
+
+TEST(CrashRecoveryTest, CallOutputDebugString) {
+ llvm::CrashRecoveryContext::Enable();
+ EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString));
+}
+
+#endif
OpenPOWER on IntegriCloud