cxa_handlers.cpp revision 439ce87946c310a093f4d39a2636ce6b4682bdac
1//===------------------------- cxa_handlers.cpp ---------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8// 9// This file implements the functionality associated with the terminate_handler, 10// unexpected_handler, and new_handler. 11//===----------------------------------------------------------------------===// 12 13#include <stdexcept> 14#include <new> 15#include <exception> 16#include "abort_message.h" 17#include "cxxabi.h" 18#include "cxa_handlers.hpp" 19#include "cxa_exception.hpp" 20#include "cxa_default_handlers.hpp" 21#include "private_typeinfo.h" 22 23namespace std 24{ 25 26 27unexpected_handler 28set_unexpected(unexpected_handler func) _NOEXCEPT 29{ 30 if (func == 0) 31 func = default_unexpected_handler; 32 return __sync_lock_test_and_set(&__cxxabiapple::__cxa_unexpected_handler, func); 33} 34 35unexpected_handler 36get_unexpected() _NOEXCEPT 37{ 38 return __sync_fetch_and_add(&__cxxabiapple::__cxa_unexpected_handler, (unexpected_handler)0); 39} 40 41__attribute__((visibility("hidden"), noreturn)) 42void 43__unexpected(unexpected_handler func) 44{ 45 func(); 46 // unexpected handler should not return 47 abort_message("unexpected_handler unexpectedly returned"); 48} 49 50__attribute__((noreturn)) 51void 52unexpected() 53{ 54 __unexpected(get_unexpected()); 55} 56 57terminate_handler 58set_terminate(terminate_handler func) _NOEXCEPT 59{ 60 if (func == 0) 61 func = default_terminate_handler; 62 return __sync_lock_test_and_set(&__cxxabiapple::__cxa_terminate_handler, func); 63} 64 65terminate_handler 66get_terminate() _NOEXCEPT 67{ 68 return __sync_fetch_and_add(&__cxxabiapple::__cxa_terminate_handler, (terminate_handler)0); 69} 70 71__attribute__((visibility("hidden"), noreturn)) 72void 73__terminate(terminate_handler func) _NOEXCEPT 74{ 75#if __has_feature(cxx_exceptions) 76 try 77 { 78#endif // __has_feature(cxx_exceptions) 79 func(); 80 // handler should not return 81 abort_message("terminate_handler unexpectedly returned"); 82#if __has_feature(cxx_exceptions) 83 } 84 catch (...) 85 { 86 // handler should not throw exception 87 abort_message("terminate_handler unexpectedly threw an exception"); 88 } 89#endif // #if __has_feature(cxx_exceptions) 90} 91 92__attribute__((noreturn)) 93void 94terminate() _NOEXCEPT 95{ 96 // If there might be an uncaught exception 97 using namespace __cxxabiv1; 98 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 99 if (globals) 100 { 101 __cxa_exception* exception_header = globals->caughtExceptions; 102 if (exception_header) 103 { 104 _Unwind_Exception* unwind_exception = 105 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; 106 bool native_exception = 107 (unwind_exception->exception_class & get_vendor_and_language) == 108 (kOurExceptionClass & get_vendor_and_language); 109 if (native_exception) 110 __terminate(exception_header->terminateHandler); 111 } 112 } 113 __terminate(get_terminate()); 114} 115 116new_handler 117set_new_handler(new_handler handler) _NOEXCEPT 118{ 119 return __sync_lock_test_and_set(&__cxxabiapple::__cxa_new_handler, handler); 120} 121 122new_handler 123get_new_handler() _NOEXCEPT 124{ 125 return __sync_fetch_and_add(&__cxxabiapple::__cxa_new_handler, (new_handler)0); 126} 127 128} // std 129