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 22namespace std 23{ 24 25unexpected_handler 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 34void 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)) 43void 44unexpected() 45{ 46 __unexpected(get_unexpected()); 47} 48 49terminate_handler 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 58void 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)) 79void 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); 104extern "C" { 105new_handler __cxa_new_handler = 0; 106} 107 108new_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 116new_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