Skip to content

Commit 4759c6e

Browse files
aganeazmodem
authored andcommitted
[Support] When using SEH, create a impl instance for CrashRecoveryContext. NFCI.
Previously, the SEH codepath in CrashRecoveryContext didn't create a CrashRecoveryContextImpl. The other codepaths (VEH and Unix) were creating it. When running with -fintegrated-cc1, this is needed to handle exit() as a jump to CrashRecoveryContext's exception filter, through a call to RaiseException. In that situation, we need a user-defined exception code, which is later interpreted as an exit() by the exception filter. This in turn needs to set RetCode accordingly, *inside* the exception filter, and *before* calling HandleCrash(). Differential Revision: https://reviews.llvm.org/D74078 (cherry picked from commit 2a3fa0f)
1 parent 64515b3 commit 4759c6e

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

llvm/lib/Support/CrashRecoveryContext.cpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <mutex>
1616
#include <setjmp.h>
1717
#ifdef _WIN32
18-
#include <excpt.h> // for GetExceptionInformation
18+
#include <windows.h> // for GetExceptionInformation
1919
#endif
2020
#if LLVM_ON_UNIX
2121
#include <sysexits.h> // EX_IOERR
@@ -41,11 +41,11 @@ struct CrashRecoveryContextImpl {
4141
::jmp_buf JumpBuffer;
4242
volatile unsigned Failed : 1;
4343
unsigned SwitchedThread : 1;
44+
unsigned ValidJumpBuffer : 1;
4445

4546
public:
46-
CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC),
47-
Failed(false),
48-
SwitchedThread(false) {
47+
CrashRecoveryContextImpl(CrashRecoveryContext *CRC)
48+
: CRC(CRC), Failed(false), SwitchedThread(false), ValidJumpBuffer(false) {
4949
Next = CurrentContext->get();
5050
CurrentContext->set(this);
5151
}
@@ -80,10 +80,13 @@ struct CrashRecoveryContextImpl {
8080
CRC->RetCode = RetCode;
8181

8282
// Jump back to the RunSafely we were called under.
83-
longjmp(JumpBuffer, 1);
83+
if (ValidJumpBuffer)
84+
longjmp(JumpBuffer, 1);
85+
86+
// Otherwise let the caller decide of the outcome of the crash. Currently
87+
// this occurs when using SEH on Windows with MSVC or clang-cl.
8488
}
8589
};
86-
8790
}
8891

8992
static ManagedStatic<std::mutex> gCrashRecoveryContextMutex;
@@ -188,37 +191,43 @@ static void uninstallExceptionOrSignalHandlers() {}
188191

189192
// We need this function because the call to GetExceptionInformation() can only
190193
// occur inside the __except evaluation block
191-
static int ExceptionFilter(bool DumpStackAndCleanup,
192-
_EXCEPTION_POINTERS *Except) {
193-
if (DumpStackAndCleanup)
194-
sys::CleanupOnSignal((uintptr_t)Except);
194+
static int ExceptionFilter(_EXCEPTION_POINTERS *Except) {
195+
// Lookup the current thread local recovery object.
196+
const CrashRecoveryContextImpl *CRCI = CurrentContext->get();
197+
198+
if (!CRCI) {
199+
// Something has gone horribly wrong, so let's just tell everyone
200+
// to keep searching
201+
CrashRecoveryContext::Disable();
202+
return EXCEPTION_CONTINUE_SEARCH;
203+
}
204+
205+
int RetCode = (int)Except->ExceptionRecord->ExceptionCode;
206+
207+
// Handle the crash
208+
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(
209+
RetCode, reinterpret_cast<uintptr_t>(Except));
210+
195211
return EXCEPTION_EXECUTE_HANDLER;
196212
}
197213

198214
#if defined(__clang__) && defined(_M_IX86)
199215
// Work around PR44697.
200216
__attribute__((optnone))
201-
static bool InvokeFunctionCall(function_ref<void()> Fn,
202-
bool DumpStackAndCleanup, int &RetCode) {
203-
#else
204-
static bool InvokeFunctionCall(function_ref<void()> Fn,
205-
bool DumpStackAndCleanup, int &RetCode) {
206217
#endif
207-
__try {
208-
Fn();
209-
} __except (ExceptionFilter(DumpStackAndCleanup, GetExceptionInformation())) {
210-
RetCode = GetExceptionCode();
211-
return false;
212-
}
213-
return true;
214-
}
215-
216218
bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
217219
if (!gCrashRecoveryEnabled) {
218220
Fn();
219221
return true;
220222
}
221-
return InvokeFunctionCall(Fn, DumpStackAndCleanupOnFailure, RetCode);
223+
assert(!Impl && "Crash recovery context already initialized!");
224+
Impl = new CrashRecoveryContextImpl(this);
225+
__try {
226+
Fn();
227+
} __except (ExceptionFilter(GetExceptionInformation())) {
228+
return false;
229+
}
230+
return true;
222231
}
223232

224233
#else // !_MSC_VER
@@ -395,6 +404,7 @@ bool CrashRecoveryContext::RunSafely(function_ref<void()> Fn) {
395404
CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this);
396405
Impl = CRCI;
397406

407+
CRCI->ValidJumpBuffer = true;
398408
if (setjmp(CRCI->JumpBuffer) != 0) {
399409
return false;
400410
}

0 commit comments

Comments
 (0)