• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
get_unexpected()26 get_unexpected() _NOEXCEPT
27 {
28     return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire);
29 }
30 
31 void
__unexpected(unexpected_handler func)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
unexpected()41 unexpected()
42 {
43     __unexpected(get_unexpected());
44 }
45 
46 terminate_handler
get_terminate()47 get_terminate() _NOEXCEPT
48 {
49     return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire);
50 }
51 
52 void
__terminate(terminate_handler func)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
terminate()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
set_new_handler(new_handler 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
get_new_handler()106 get_new_handler() _NOEXCEPT
107 {
108     return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
109 }
110 
111 }  // std
112