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 "private_typeinfo.h" 21 22 namespace std 23 { 24 25 unexpected_handler get_unexpected()26get_unexpected() _NOEXCEPT 27 { 28 return __sync_fetch_and_add(&__cxa_unexpected_handler, (unexpected_handler)0); 29 // The above is safe but overkill on x86 30 // Using of C++11 atomics this should be rewritten 31 // return __cxa_unexpected_handler.load(memory_order_acq); 32 } 33 34 void __unexpected(unexpected_handler func)35__unexpected(unexpected_handler func) 36 { 37 func(); 38 // unexpected handler should not return 39 abort_message("unexpected_handler unexpectedly returned"); 40 } 41 42 __attribute__((noreturn)) 43 void unexpected()44unexpected() 45 { 46 __unexpected(get_unexpected()); 47 } 48 49 terminate_handler get_terminate()50get_terminate() _NOEXCEPT 51 { 52 return __sync_fetch_and_add(&__cxa_terminate_handler, (terminate_handler)0); 53 // The above is safe but overkill on x86 54 // Using of C++11 atomics this should be rewritten 55 // return __cxa_terminate_handler.load(memory_order_acq); 56 } 57 58 void __terminate(terminate_handler func)59__terminate(terminate_handler func) _NOEXCEPT 60 { 61 #ifndef _LIBCXXABI_NO_EXCEPTIONS 62 try 63 { 64 #endif // _LIBCXXABI_NO_EXCEPTIONS 65 func(); 66 // handler should not return 67 abort_message("terminate_handler unexpectedly returned"); 68 #ifndef _LIBCXXABI_NO_EXCEPTIONS 69 } 70 catch (...) 71 { 72 // handler should not throw exception 73 abort_message("terminate_handler unexpectedly threw an exception"); 74 } 75 #endif // _LIBCXXABI_NO_EXCEPTIONS 76 } 77 78 __attribute__((noreturn)) 79 void terminate()80terminate() _NOEXCEPT 81 { 82 // If there might be an uncaught exception 83 using namespace __cxxabiv1; 84 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 85 if (globals) 86 { 87 __cxa_exception* exception_header = globals->caughtExceptions; 88 if (exception_header) 89 { 90 _Unwind_Exception* unwind_exception = 91 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; 92 bool native_exception = 93 (unwind_exception->exception_class & get_vendor_and_language) == 94 (kOurExceptionClass & get_vendor_and_language); 95 if (native_exception) 96 __terminate(exception_header->terminateHandler); 97 } 98 } 99 __terminate(get_terminate()); 100 } 101 102 // In the future this will become: 103 // std::atomic<std::new_handler> __cxa_new_handler(0); 104 extern "C" { 105 new_handler __cxa_new_handler = 0; 106 } 107 108 new_handler set_new_handler(new_handler handler)109set_new_handler(new_handler handler) _NOEXCEPT 110 { 111 return __atomic_exchange_n(&__cxa_new_handler, handler, __ATOMIC_ACQ_REL); 112 // Using of C++11 atomics this should be rewritten 113 // return __cxa_new_handler.exchange(handler, memory_order_acq_rel); 114 } 115 116 new_handler get_new_handler()117get_new_handler() _NOEXCEPT 118 { 119 return __sync_fetch_and_add(&__cxa_new_handler, (new_handler)0); 120 // The above is safe but overkill on x86 121 // Using of C++11 atomics this should be rewritten 122 // return __cxa_new_handler.load(memory_order_acq); 123 } 124 125 } // std 126