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