OLD | NEW |
(Empty) | |
| 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 |
| 26 get_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 __attribute__((visibility("hidden"), noreturn)) |
| 35 void |
| 36 __unexpected(unexpected_handler func) |
| 37 { |
| 38 func(); |
| 39 // unexpected handler should not return |
| 40 abort_message("unexpected_handler unexpectedly returned"); |
| 41 } |
| 42 |
| 43 __attribute__((noreturn)) |
| 44 void |
| 45 unexpected() |
| 46 { |
| 47 __unexpected(get_unexpected()); |
| 48 } |
| 49 |
| 50 terminate_handler |
| 51 get_terminate() _NOEXCEPT |
| 52 { |
| 53 return __sync_fetch_and_add(&__cxa_terminate_handler, (terminate_handler)0); |
| 54 // The above is safe but overkill on x86 |
| 55 // Using of C++11 atomics this should be rewritten |
| 56 // return __cxa_terminate_handler.load(memory_order_acq); |
| 57 } |
| 58 |
| 59 __attribute__((visibility("hidden"), noreturn)) |
| 60 void |
| 61 __terminate(terminate_handler func) _NOEXCEPT |
| 62 { |
| 63 #if __has_feature(cxx_exceptions) |
| 64 try |
| 65 { |
| 66 #endif // __has_feature(cxx_exceptions) |
| 67 func(); |
| 68 // handler should not return |
| 69 abort_message("terminate_handler unexpectedly returned"); |
| 70 #if __has_feature(cxx_exceptions) |
| 71 } |
| 72 catch (...) |
| 73 { |
| 74 // handler should not throw exception |
| 75 abort_message("terminate_handler unexpectedly threw an exception"); |
| 76 } |
| 77 #endif // #if __has_feature(cxx_exceptions) |
| 78 } |
| 79 |
| 80 __attribute__((noreturn)) |
| 81 void |
| 82 terminate() _NOEXCEPT |
| 83 { |
| 84 // If there might be an uncaught exception |
| 85 using namespace __cxxabiv1; |
| 86 __cxa_eh_globals* globals = __cxa_get_globals_fast(); |
| 87 if (globals) |
| 88 { |
| 89 __cxa_exception* exception_header = globals->caughtExceptions; |
| 90 if (exception_header) |
| 91 { |
| 92 _Unwind_Exception* unwind_exception = |
| 93 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; |
| 94 bool native_exception = |
| 95 (unwind_exception->exception_class & get_vendor_and_language) == |
| 96 (kOurExceptionClass & get_vendor_and_language); |
| 97 if (native_exception) |
| 98 __terminate(exception_header->terminateHandler); |
| 99 } |
| 100 } |
| 101 __terminate(get_terminate()); |
| 102 } |
| 103 |
| 104 extern "C" new_handler __cxa_new_handler = 0; |
| 105 // In the future these will become: |
| 106 // std::atomic<std::new_handler> __cxa_new_handler(0); |
| 107 |
| 108 new_handler |
| 109 set_new_handler(new_handler handler) _NOEXCEPT |
| 110 { |
| 111 return __sync_swap(&__cxa_new_handler, handler); |
| 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 |
| 117 get_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 |
OLD | NEW |