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 void
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
44 unexpected()
45 {
46     __unexpected(get_unexpected());
47 }
48 
49 terminate_handler
50 get_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
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
80 terminate() _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
109 set_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
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
126