150
|
1 //===------------------------- cxa_handlers.cpp ---------------------------===//
|
|
2 //
|
|
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
4 // See https://llvm.org/LICENSE.txt for license information.
|
|
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
6 //
|
|
7 //
|
|
8 // This file implements the functionality associated with the terminate_handler,
|
|
9 // unexpected_handler, and new_handler.
|
|
10 //===----------------------------------------------------------------------===//
|
|
11
|
|
12 #include <stdexcept>
|
|
13 #include <new>
|
|
14 #include <exception>
|
|
15 #include "abort_message.h"
|
|
16 #include "cxxabi.h"
|
|
17 #include "cxa_handlers.h"
|
|
18 #include "cxa_exception.h"
|
|
19 #include "private_typeinfo.h"
|
|
20 #include "include/atomic_support.h"
|
|
21
|
|
22 namespace std
|
|
23 {
|
|
24
|
|
25 unexpected_handler
|
|
26 get_unexpected() _NOEXCEPT
|
|
27 {
|
|
28 return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire);
|
|
29 }
|
|
30
|
|
31 void
|
|
32 __unexpected(unexpected_handler func)
|
|
33 {
|
|
34 func();
|
|
35 // unexpected handler should not return
|
|
36 abort_message("unexpected_handler unexpectedly returned");
|
|
37 }
|
|
38
|
|
39 __attribute__((noreturn))
|
|
40 void
|
|
41 unexpected()
|
|
42 {
|
|
43 __unexpected(get_unexpected());
|
|
44 }
|
|
45
|
|
46 terminate_handler
|
|
47 get_terminate() _NOEXCEPT
|
|
48 {
|
|
49 return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire);
|
|
50 }
|
|
51
|
|
52 void
|
|
53 __terminate(terminate_handler func) _NOEXCEPT
|
|
54 {
|
|
55 #ifndef _LIBCXXABI_NO_EXCEPTIONS
|
|
56 try
|
|
57 {
|
|
58 #endif // _LIBCXXABI_NO_EXCEPTIONS
|
|
59 func();
|
|
60 // handler should not return
|
|
61 abort_message("terminate_handler unexpectedly returned");
|
|
62 #ifndef _LIBCXXABI_NO_EXCEPTIONS
|
|
63 }
|
|
64 catch (...)
|
|
65 {
|
|
66 // handler should not throw exception
|
|
67 abort_message("terminate_handler unexpectedly threw an exception");
|
|
68 }
|
|
69 #endif // _LIBCXXABI_NO_EXCEPTIONS
|
|
70 }
|
|
71
|
|
72 __attribute__((noreturn))
|
|
73 void
|
|
74 terminate() _NOEXCEPT
|
|
75 {
|
|
76 #ifndef _LIBCXXABI_NO_EXCEPTIONS
|
|
77 // If there might be an uncaught exception
|
|
78 using namespace __cxxabiv1;
|
|
79 __cxa_eh_globals* globals = __cxa_get_globals_fast();
|
|
80 if (globals)
|
|
81 {
|
|
82 __cxa_exception* exception_header = globals->caughtExceptions;
|
|
83 if (exception_header)
|
|
84 {
|
|
85 _Unwind_Exception* unwind_exception =
|
|
86 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
|
|
87 if (__isOurExceptionClass(unwind_exception))
|
|
88 __terminate(exception_header->terminateHandler);
|
|
89 }
|
|
90 }
|
|
91 #endif
|
|
92 __terminate(get_terminate());
|
|
93 }
|
|
94
|
|
95 extern "C" {
|
|
96 new_handler __cxa_new_handler = 0;
|
|
97 }
|
|
98
|
|
99 new_handler
|
|
100 set_new_handler(new_handler handler) _NOEXCEPT
|
|
101 {
|
|
102 return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
|
|
103 }
|
|
104
|
|
105 new_handler
|
|
106 get_new_handler() _NOEXCEPT
|
|
107 {
|
|
108 return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
|
|
109 }
|
|
110
|
|
111 } // std
|