cxa_handlers.cpp revision 7da9b96afc66c4496eb8809897c1b707b574a5c4
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 25static const char* cause = "uncaught"; 26 27static void default_terminate_handler() 28{ 29 // If there might be an uncaught exception 30 using namespace __cxxabiv1; 31 __cxa_eh_globals* globals = __cxa_get_globals_fast(); 32 if (globals) 33 { 34 __cxa_exception* exception_header = globals->caughtExceptions; 35 // If there is an uncaught exception 36 if (exception_header) 37 { 38 _Unwind_Exception* unwind_exception = 39 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; 40 bool native_exception = (unwind_exception->exception_class & get_language) == 41 (kOurExceptionClass & get_language); 42 if (native_exception) 43 { 44 void* thrown_object = 45 unwind_exception->exception_class == kOurDependentExceptionClass ? 46 ((__cxa_dependent_exception*)exception_header)->primaryException : 47 exception_header + 1; 48 const __shim_type_info* thrown_type = 49 static_cast<const __shim_type_info*>(exception_header->exceptionType); 50 const __shim_type_info* catch_type = 51 static_cast<const __shim_type_info*>(&typeid(exception)); 52 // If the uncaught exception can be caught with std::exception& 53 if (catch_type->can_catch(thrown_type, thrown_object)) 54 { 55 // Include the what() message from the exception 56 const exception* e = static_cast<const exception*>(thrown_object); 57 abort_message("terminating with %s exception of type %s: %s", 58 cause, thrown_type->name(), e->what()); 59 } 60 else 61 // Else just note that we're terminating with an exception 62 abort_message("terminating with %s exception of type %s", 63 cause, thrown_type->name()); 64 } 65 else 66 // Else we're terminating with a foreign exception 67 abort_message("terminating with %s foreign exception", cause); 68 } 69 } 70 // Else just note that we're terminating 71 abort_message("terminating"); 72} 73 74static void default_unexpected_handler() 75{ 76 cause = "unexpected"; 77 terminate(); 78} 79 80static terminate_handler __terminate_handler = default_terminate_handler; 81static unexpected_handler __unexpected_handler = default_unexpected_handler; 82static new_handler __new_handler = 0; 83 84unexpected_handler 85set_unexpected(unexpected_handler func) _NOEXCEPT 86{ 87 if (func == 0) 88 func = default_unexpected_handler; 89 return __sync_lock_test_and_set(&__unexpected_handler, func); 90} 91 92unexpected_handler 93get_unexpected() _NOEXCEPT 94{ 95 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); 96} 97 98__attribute__((visibility("hidden"), noreturn)) 99void 100__unexpected(unexpected_handler func) 101{ 102 func(); 103 // unexpected handler should not return 104 abort_message("unexpected_handler unexpectedly returned"); 105} 106 107__attribute__((noreturn)) 108void 109unexpected() 110{ 111 __unexpected(get_unexpected()); 112} 113 114terminate_handler 115set_terminate(terminate_handler func) _NOEXCEPT 116{ 117 if (func == 0) 118 func = default_terminate_handler; 119 return __sync_lock_test_and_set(&__terminate_handler, func); 120} 121 122terminate_handler 123get_terminate() _NOEXCEPT 124{ 125 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); 126} 127 128__attribute__((visibility("hidden"), noreturn)) 129void 130__terminate(terminate_handler func) _NOEXCEPT 131{ 132#if __has_feature(cxx_exceptions) 133 try 134 { 135#endif // __has_feature(cxx_exceptions) 136 func(); 137 // handler should not return 138 abort_message("terminate_handler unexpectedly returned"); 139#if __has_feature(cxx_exceptions) 140 } 141 catch (...) 142 { 143 // handler should not throw exception 144 abort_message("terminate_handler unexpectedly threw an exception"); 145 } 146#endif // #if __has_feature(cxx_exceptions) 147} 148 149__attribute__((noreturn)) 150void 151terminate() _NOEXCEPT 152{ 153 __terminate(get_terminate()); 154} 155 156new_handler 157set_new_handler(new_handler handler) _NOEXCEPT 158{ 159 return __sync_lock_test_and_set(&__new_handler, handler); 160} 161 162new_handler 163get_new_handler() _NOEXCEPT 164{ 165 return __sync_fetch_and_add(&__new_handler, (new_handler)0); 166} 167 168} // std 169