Add objc_setUncaughtExceptionHandler() API

main
Frederik Seiffert 2 years ago committed by Frederik Seiffert
parent 0aea4b2e93
commit 3b6b960810

@ -84,6 +84,7 @@ set(libobjc_HDRS
objc/objc-arc.h
objc/objc-auto.h
objc/objc-class.h
objc/objc-exception.h
objc/objc-runtime.h
objc/objc-visibility.h
objc/objc.h

@ -34,7 +34,7 @@ int main(void)
SetUnhandledExceptionFilter(&_UnhandledExceptionFilter);
#endif
_objc_unexpected_exception = _UncaughtExceptionHandler;
objc_setUncaughtExceptionHandler(_UncaughtExceptionHandler);
@throw exceptionObj;
assert(0 && "should not be reached!");

@ -4,6 +4,7 @@
#include "dwarf_eh.h"
#include "objc/runtime.h"
#include "objc/hooks.h"
#include "objc/objc-exception.h"
#include "class.h"
#include "objcxx_eh.h"
@ -760,3 +761,8 @@ void objc_exception_rethrow(struct _Unwind_Exception *e)
_Unwind_Resume_or_Rethrow(e);
abort();
}
objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler)
{
return __atomic_exchange_n(&_objc_unexpected_exception, handler, __ATOMIC_SEQ_CST);
}

@ -4,7 +4,7 @@
#include <vector>
#include "objc/runtime.h"
#include "objc/hooks.h"
#include "objc/objc-exception.h"
#include "visibility.h"
#include <windows.h>
@ -57,6 +57,7 @@ struct _MSVC_ThrowInfo
};
static LPTOP_LEVEL_EXCEPTION_FILTER originalUnhandledExceptionFilter = nullptr;
void (*_objc_unexpected_exception)(id exception);
LONG WINAPI _objc_unhandled_exception_filter(struct _EXCEPTION_POINTERS* exceptionInfo);
#if defined(_WIN64)
@ -197,17 +198,6 @@ OBJC_PUBLIC extern "C" void objc_exception_throw(id object)
exception.ExceptionInformation[2] = reinterpret_cast<ULONG_PTR>(&ti);
exception.ExceptionInformation[3] = reinterpret_cast<ULONG_PTR>(&x);
// Set unhandled exception filter to support _objc_unexpected_exception hook.
// Unfortunately there doesn't seem to be a better place to call this, as
// installing it at construction time means that it will get overwritten by
// the handler installed by the VC runtime. This way it works, but as a side
// effect throwing exceptions will overwrite any previously installed handler,
// so we save it and call it as part of our handler.
LPTOP_LEVEL_EXCEPTION_FILTER previousExceptionFilter = SetUnhandledExceptionFilter(&_objc_unhandled_exception_filter);
if (previousExceptionFilter != &_objc_unhandled_exception_filter) {
originalUnhandledExceptionFilter = previousExceptionFilter;
}
#ifdef _WIN64
RtlRaiseException(&exception);
#else
@ -282,3 +272,16 @@ LONG WINAPI _objc_unhandled_exception_filter(struct _EXCEPTION_POINTERS* excepti
// Since this is the last one, it is not likely to find any more.
return EXCEPTION_CONTINUE_SEARCH;
}
OBJC_PUBLIC extern "C" 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);
// set unhandled exception filter to support hook
LPTOP_LEVEL_EXCEPTION_FILTER previousExceptionFilter = SetUnhandledExceptionFilter(&_objc_unhandled_exception_filter);
if (previousExceptionFilter != &_objc_unhandled_exception_filter) {
originalUnhandledExceptionFilter = previousExceptionFilter;
}
return previousHandler;
}

@ -46,12 +46,17 @@ OBJC_PUBLIC extern struct objc_slot *(*__objc_msg_forward3)(id, SEL) OBJC_DEPREC
* handles the forwarding.
*/
OBJC_PUBLIC extern IMP (*__objc_msg_forward2)(id, SEL);
#ifndef _WIN32
/**
* Hook defined for handling unhandled exceptions. If the unwind library
* reaches the end of the stack without finding a handler then this hook is
* called.
* Deprecated. Use objc_setUncaughtExceptionHandler() instead.
*/
OBJC_HOOK void (*_objc_unexpected_exception)(id exception);
#endif
/**
* Hook defined to return the class to be used for boxing a foreign exception
* type. The class must implement:

@ -0,0 +1,33 @@
#if defined(__clang__) && !defined(__OBJC_RUNTIME_INTERNAL__)
#pragma clang system_header
#endif
#include "objc-visibility.h"
#ifndef __OBJC_EXCEPTION_INCLUDED__
#define __OBJC_EXCEPTION_INCLUDED__
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*objc_uncaught_exception_handler)(id exception);
/**
* Throw a runtime exception. Inserted by the compiler in place of @throw.
*/
OBJC_PUBLIC
void objc_exception_throw(id object);
/**
* Installs handler for uncaught Objective-C exceptions. If the unwind library
* reaches the end of the stack without finding a handler then the handler is
* called. Returns the previous handler.
*/
OBJC_PUBLIC
objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler handler);
#ifdef __cplusplus
}
#endif
#endif // __OBJC_EXCEPTION_INCLUDED__
Loading…
Cancel
Save