<div dir="ltr"><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/5002/steps/check-llvm%20asan/logs/stdio" class="cremed">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/5002/steps/check-llvm%20asan/logs/stdio</a><div><br></div><div><pre style="font-family:"Courier New",courier,monotype,monospace;font-size:medium"><span class="inbox-inbox-stdout">SAN:DEADLYSIGNAL
=================================================================
==24802==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000660cef bp 0x7fffa59551f0 sp 0x7fffa59551f0 T0)
==24802==The signal is caused by a WRITE memory access.
==24802==Hint: address points to the zero page.
#0 0x660cee in nullDeref() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/Support/CrashRecoveryTest.cpp:24:52
#1 0xc7e51b in operator() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/STLExtras.h:111:12
#2 0xc7e51b in llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Support/CrashRecoveryContext.cpp:359
#3 0x6614a1 in CrashRecoveryTest_Cleanup_Test::TestBody() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/Support/CrashRecoveryTest.cpp:59:5
#4 0xdc9a3e in HandleExceptionsInMethodIfSupported<testing::Test, void> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12
#5 0xdc9a3e in testing::Test::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2474
#6 0xdce174 in testing::TestInfo::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2656:11
#7 0xdcf4a6 in testing::TestCase::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2774:28
#8 0xdef336 in testing::internal::UnitTestImpl::RunAllTests() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:4649:43
#9 0xdee692 in HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12
#10 0xdee692 in testing::UnitTest::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:4257
#11 0xdad59b in RUN_ALL_TESTS /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/include/gtest/gtest.h:2233:46
#12 0xdad59b in main /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/UnitTestMain/TestMain.cpp:51
#13 0x7ff81ab8982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#14 0x485d98 in _start (/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build_asan/unittests/Support/SupportTests+0x485d98)
</span></pre><br class="inbox-inbox-Apple-interchange-newline"></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, May 17, 2017 at 11:29 AM Reid Kleckner via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Wed May 17 13:16:17 2017<br>
New Revision: 303279<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=303279&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=303279&view=rev</a><br>
Log:<br>
Re-land r303274: "[CrashRecovery] Use SEH __try instead of VEH when available"<br>
<br>
We have to check gCrashRecoveryEnabled before using __try.<br>
<br>
In other words, SEH works too well and we ended up recovering from<br>
crashes in implicit module builds that we weren't supposed to. Only<br>
libclang is supposed to enable CrashRecoveryContext to allow implicit<br>
module builds to crash.<br>
<br>
Added:<br>
llvm/trunk/unittests/Support/CrashRecoveryTest.cpp<br>
Modified:<br>
llvm/trunk/lib/Support/CrashRecoveryContext.cpp<br>
llvm/trunk/unittests/Support/CMakeLists.txt<br>
<br>
Modified: llvm/trunk/lib/Support/CrashRecoveryContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CrashRecoveryContext.cpp?rev=303279&r1=303278&r2=303279&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CrashRecoveryContext.cpp?rev=303279&r1=303278&r2=303279&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/CrashRecoveryContext.cpp (original)<br>
+++ llvm/trunk/lib/Support/CrashRecoveryContext.cpp Wed May 17 13:16:17 2017<br>
@@ -78,6 +78,9 @@ static bool gCrashRecoveryEnabled = fals<br>
static ManagedStatic<sys::ThreadLocal<const CrashRecoveryContext>><br>
tlIsRecoveringFromCrash;<br>
<br>
+static void installExceptionOrSignalHandlers();<br>
+static void uninstallExceptionOrSignalHandlers();<br>
+<br>
CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() {}<br>
<br>
CrashRecoveryContext::~CrashRecoveryContext() {<br>
@@ -113,6 +116,23 @@ CrashRecoveryContext *CrashRecoveryConte<br>
return CRCI->CRC;<br>
}<br>
<br>
+void CrashRecoveryContext::Enable() {<br>
+ sys::ScopedLock L(*gCrashRecoveryContextMutex);<br>
+ // FIXME: Shouldn't this be a refcount or something?<br>
+ if (gCrashRecoveryEnabled)<br>
+ return;<br>
+ gCrashRecoveryEnabled = true;<br>
+ installExceptionOrSignalHandlers();<br>
+}<br>
+<br>
+void CrashRecoveryContext::Disable() {<br>
+ sys::ScopedLock L(*gCrashRecoveryContextMutex);<br>
+ if (!gCrashRecoveryEnabled)<br>
+ return;<br>
+ gCrashRecoveryEnabled = false;<br>
+ uninstallExceptionOrSignalHandlers();<br>
+}<br>
+<br>
void CrashRecoveryContext::registerCleanup(CrashRecoveryContextCleanup *cleanup)<br>
{<br>
if (!cleanup)<br>
@@ -140,27 +160,56 @@ CrashRecoveryContext::unregisterCleanup(<br>
delete cleanup;<br>
}<br>
<br>
-#ifdef LLVM_ON_WIN32<br>
+#if defined(_MSC_VER)<br>
+// If _MSC_VER is defined, we must have SEH. Use it if it's available. It's way<br>
+// better than VEH. Vectored exception handling catches all exceptions happening<br>
+// on the thread with installed exception handlers, so it can interfere with<br>
+// internal exception handling of other libraries on that thread. SEH works<br>
+// exactly as you would expect normal exception handling to work: it only<br>
+// catches exceptions if they would bubble out from the stack frame with __try /<br>
+// __except.<br>
<br>
-#include "Windows/WindowsSupport.h"<br>
+static void installExceptionOrSignalHandlers() {}<br>
+static void uninstallExceptionOrSignalHandlers() {}<br>
+<br>
+bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {<br>
+ if (!gCrashRecoveryEnabled) {<br>
+ Fn();<br>
+ return true;<br>
+ }<br>
+<br>
+ bool Result = true;<br>
+ __try {<br>
+ Fn();<br>
+ } __except (1) { // Catch any exception.<br>
+ Result = false;<br>
+ }<br>
+ return Result;<br>
+}<br>
+<br>
+#else // !_MSC_VER<br>
<br>
-// On Windows, we can make use of vectored exception handling to<br>
-// catch most crashing situations. Note that this does mean<br>
-// we will be alerted of exceptions *before* structured exception<br>
-// handling has the opportunity to catch it. But that isn't likely<br>
-// to cause problems because nowhere in the project is SEH being<br>
-// used.<br>
+#if defined(LLVM_ON_WIN32)<br>
+// This is a non-MSVC compiler, probably mingw gcc or clang without<br>
+// -fms-extensions. Use vectored exception handling (VEH).<br>
//<br>
-// Vectored exception handling is built on top of SEH, and so it<br>
-// works on a per-thread basis.<br>
+// On Windows, we can make use of vectored exception handling to catch most<br>
+// crashing situations. Note that this does mean we will be alerted of<br>
+// exceptions *before* structured exception handling has the opportunity to<br>
+// catch it. Unfortunately, this causes problems in practice with other code<br>
+// running on threads with LLVM crash recovery contexts, so we would like to<br>
+// eventually move away from VEH.<br>
+//<br>
+// Vectored works on a per-thread basis, which is an advantage over<br>
+// SetUnhandledExceptionFilter. SetUnhandledExceptionFilter also doesn't have<br>
+// any native support for chaining exception handlers, but VEH allows more than<br>
+// one.<br>
//<br>
// The vectored exception handler functionality was added in Windows<br>
// XP, so if support for older versions of Windows is required,<br>
// it will have to be added.<br>
-//<br>
-// If we want to support as far back as Win2k, we could use the<br>
-// SetUnhandledExceptionFilter API, but there's a risk of that<br>
-// being entirely overwritten (it's not a chain).<br>
+<br>
+#include "Windows/WindowsSupport.h"<br>
<br>
static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)<br>
{<br>
@@ -203,14 +252,7 @@ static LONG CALLBACK ExceptionHandler(PE<br>
// non-NULL, valid VEH handles, or NULL.<br>
static sys::ThreadLocal<const void> sCurrentExceptionHandle;<br>
<br>
-void CrashRecoveryContext::Enable() {<br>
- sys::ScopedLock L(*gCrashRecoveryContextMutex);<br>
-<br>
- if (gCrashRecoveryEnabled)<br>
- return;<br>
-<br>
- gCrashRecoveryEnabled = true;<br>
-<br>
+static void installExceptionOrSignalHandlers() {<br>
// We can set up vectored exception handling now. We will install our<br>
// handler as the front of the list, though there's no assurances that<br>
// it will remain at the front (another call could install itself before<br>
@@ -219,14 +261,7 @@ void CrashRecoveryContext::Enable() {<br>
sCurrentExceptionHandle.set(handle);<br>
}<br>
<br>
-void CrashRecoveryContext::Disable() {<br>
- sys::ScopedLock L(*gCrashRecoveryContextMutex);<br>
-<br>
- if (!gCrashRecoveryEnabled)<br>
- return;<br>
-<br>
- gCrashRecoveryEnabled = false;<br>
-<br>
+static void uninstallExceptionOrSignalHandlers() {<br>
PVOID currentHandle = const_cast<PVOID>(sCurrentExceptionHandle.get());<br>
if (currentHandle) {<br>
// Now we can remove the vectored exception handler from the chain<br>
@@ -237,7 +272,7 @@ void CrashRecoveryContext::Disable() {<br>
}<br>
}<br>
<br>
-#else<br>
+#else // !LLVM_ON_WIN32<br>
<br>
// Generic POSIX implementation.<br>
//<br>
@@ -289,14 +324,7 @@ static void CrashRecoverySignalHandler(i<br>
const_cast<CrashRecoveryContextImpl*>(CRCI)->HandleCrash();<br>
}<br>
<br>
-void CrashRecoveryContext::Enable() {<br>
- sys::ScopedLock L(*gCrashRecoveryContextMutex);<br>
-<br>
- if (gCrashRecoveryEnabled)<br>
- return;<br>
-<br>
- gCrashRecoveryEnabled = true;<br>
-<br>
+static void installExceptionOrSignalHandlers() {<br>
// Setup the signal handler.<br>
struct sigaction Handler;<br>
Handler.sa_handler = CrashRecoverySignalHandler;<br>
@@ -308,20 +336,13 @@ void CrashRecoveryContext::Enable() {<br>
}<br>
}<br>
<br>
-void CrashRecoveryContext::Disable() {<br>
- sys::ScopedLock L(*gCrashRecoveryContextMutex);<br>
-<br>
- if (!gCrashRecoveryEnabled)<br>
- return;<br>
-<br>
- gCrashRecoveryEnabled = false;<br>
-<br>
+static void uninstallExceptionOrSignalHandlers() {<br>
// Restore the previous signal handlers.<br>
for (unsigned i = 0; i != NumSignals; ++i)<br>
sigaction(Signals[i], &PrevActions[i], nullptr);<br>
}<br>
<br>
-#endif<br>
+#endif // !LLVM_ON_WIN32<br>
<br>
bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {<br>
// If crash recovery is disabled, do nothing.<br>
@@ -339,6 +360,8 @@ bool CrashRecoveryContext::RunSafely(fun<br>
return true;<br>
}<br>
<br>
+#endif // !_MSC_VER<br>
+<br>
void CrashRecoveryContext::HandleCrash() {<br>
CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl;<br>
assert(CRCI && "Crash recovery context never initialized!");<br>
<br>
Modified: llvm/trunk/unittests/Support/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=303279&r1=303278&r2=303279&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CMakeLists.txt?rev=303279&r1=303278&r2=303279&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/Support/CMakeLists.txt (original)<br>
+++ llvm/trunk/unittests/Support/CMakeLists.txt Wed May 17 13:16:17 2017<br>
@@ -11,6 +11,7 @@ add_llvm_unittest(SupportTests<br>
BlockFrequencyTest.cpp<br>
BranchProbabilityTest.cpp<br>
CachePruningTest.cpp<br>
+ CrashRecoveryTest.cpp<br>
Casting.cpp<br>
Chrono.cpp<br>
CommandLineTest.cpp<br>
<br>
Added: llvm/trunk/unittests/Support/CrashRecoveryTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CrashRecoveryTest.cpp?rev=303279&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/CrashRecoveryTest.cpp?rev=303279&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/Support/CrashRecoveryTest.cpp (added)<br>
+++ llvm/trunk/unittests/Support/CrashRecoveryTest.cpp Wed May 17 13:16:17 2017<br>
@@ -0,0 +1,83 @@<br>
+//===- llvm/unittest/Support/CrashRecoveryTest.cpp ------------------------===//<br>
+//<br>
+// The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/Support/CrashRecoveryContext.h"<br>
+#include "llvm/Support/Compiler.h"<br>
+#include "gtest/gtest.h"<br>
+<br>
+#ifdef LLVM_ON_WIN32<br>
+#define WIN32_LEAN_AND_MEAN<br>
+#define NOGDI<br>
+#include <windows.h><br>
+#endif<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::sys;<br>
+<br>
+static int GlobalInt = 0;<br>
+static void nullDeref() { *(volatile int *)nullptr = 0; }<br>
+static void incrementGlobal() { ++GlobalInt; }<br>
+static void llvmTrap() { LLVM_BUILTIN_TRAP; }<br>
+<br>
+TEST(CrashRecoveryTest, Basic) {<br>
+ llvm::CrashRecoveryContext::Enable();<br>
+ GlobalInt = 0;<br>
+ EXPECT_TRUE(CrashRecoveryContext().RunSafely(incrementGlobal));<br>
+ EXPECT_EQ(1, GlobalInt);<br>
+ EXPECT_FALSE(CrashRecoveryContext().RunSafely(nullDeref));<br>
+ EXPECT_FALSE(CrashRecoveryContext().RunSafely(llvmTrap));<br>
+}<br>
+<br>
+struct IncrementGlobalCleanup : CrashRecoveryContextCleanup {<br>
+ IncrementGlobalCleanup(CrashRecoveryContext *CRC)<br>
+ : CrashRecoveryContextCleanup(CRC) {}<br>
+ virtual void recoverResources() { ++GlobalInt; }<br>
+};<br>
+<br>
+static void noop() {}<br>
+<br>
+TEST(CrashRecoveryTest, Cleanup) {<br>
+ llvm::CrashRecoveryContext::Enable();<br>
+ GlobalInt = 0;<br>
+ {<br>
+ CrashRecoveryContext CRC;<br>
+ CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));<br>
+ EXPECT_TRUE(CRC.RunSafely(noop));<br>
+ } // run cleanups<br>
+ EXPECT_EQ(1, GlobalInt);<br>
+<br>
+ GlobalInt = 0;<br>
+ {<br>
+ CrashRecoveryContext CRC;<br>
+ CRC.registerCleanup(new IncrementGlobalCleanup(&CRC));<br>
+ EXPECT_FALSE(CRC.RunSafely(nullDeref));<br>
+ } // run cleanups<br>
+ EXPECT_EQ(1, GlobalInt);<br>
+}<br>
+<br>
+#ifdef LLVM_ON_WIN32<br>
+static void raiseIt() {<br>
+ RaiseException(123, EXCEPTION_NONCONTINUABLE, 0, NULL);<br>
+}<br>
+<br>
+TEST(CrashRecoveryTest, RaiseException) {<br>
+ llvm::CrashRecoveryContext::Enable();<br>
+ EXPECT_FALSE(CrashRecoveryContext().RunSafely(raiseIt));<br>
+}<br>
+<br>
+static void outputString() {<br>
+ OutputDebugStringA("output for debugger\n");<br>
+}<br>
+<br>
+TEST(CrashRecoveryTest, CallOutputDebugString) {<br>
+ llvm::CrashRecoveryContext::Enable();<br>
+ EXPECT_TRUE(CrashRecoveryContext().RunSafely(outputString));<br>
+}<br>
+<br>
+#endif<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>