-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use C++ exceptions unconditionally for Objective-C[++] on MinGW (#267)
- Loading branch information
1 parent
3c42c64
commit 6528090
Showing
4 changed files
with
105 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters