Use C++ exceptions unconditionally for Objective-C[++] on MinGW (#267)
parent
3c42c64c14
commit
65280908eb
@ -0,0 +1,59 @@
|
||||
#include "objc/runtime.h"
|
||||
#include "objc/objc-exception.h"
|
||||
#include "objc/hooks.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define STATUS_GCC_THROW 0x20474343
|
||||
|
||||
extern void *__cxa_current_exception_type(void);
|
||||
extern void __cxa_rethrow();
|
||||
|
||||
BOOL handler_installed = NO;
|
||||
_Thread_local BOOL in_handler = NO;
|
||||
|
||||
// This vectored exception handler is the last handler to get invoke for every exception (Objective C or foreign).
|
||||
// It calls _objc_unexpected_exception only when the exception is a C++ exception (ex->ExceptionCode == STATUS_GCC_THROW)
|
||||
// and the exception is an Objective C exception.
|
||||
// It always returns EXCEPTION_CONTINUE_SEARCH, so Windows will continue handling the exception.
|
||||
static LONG CALLBACK _objc_vectored_exception_handler(EXCEPTION_POINTERS* exceptionInfo)
|
||||
{
|
||||
const EXCEPTION_RECORD* ex = exceptionInfo->ExceptionRecord;
|
||||
|
||||
if (_objc_unexpected_exception != 0
|
||||
&& ex->ExceptionCode == STATUS_GCC_THROW
|
||||
&& !in_handler)
|
||||
{
|
||||
// Rethrow the current exception and use the @catch clauses to determine whether it's an Objective C exception
|
||||
// or a foreign exception.
|
||||
if (__cxa_current_exception_type()) {
|
||||
in_handler = YES;
|
||||
@try {
|
||||
__cxa_rethrow();
|
||||
} @catch (id e) {
|
||||
// Invoke _objc_unexpected_exception for Objective C exceptions
|
||||
(*_objc_unexpected_exception)((id)e);
|
||||
} @catch (...) {
|
||||
// Ignore foreign exceptions.
|
||||
}
|
||||
in_handler = NO;
|
||||
}
|
||||
}
|
||||
|
||||
// EXCEPTION_CONTINUE_SEARCH instructs the exception handler to continue searching for appropriate exception handlers.
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
OBJC_PUBLIC extern objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler)
|
||||
{
|
||||
objc_uncaught_exception_handler previousHandler = __atomic_exchange_n(&_objc_unexpected_exception, handler, __ATOMIC_SEQ_CST);
|
||||
|
||||
// Add a vectored exception handler to support the hook. We only need to do this once.
|
||||
if (!handler_installed) {
|
||||
AddVectoredExceptionHandler(0 /* The handler is the last handler to be called */ , _objc_vectored_exception_handler);
|
||||
handler_installed = YES;
|
||||
}
|
||||
|
||||
return previousHandler;
|
||||
}
|
||||
Loading…
Reference in New Issue