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.hpp"
18#include "cxa_exception.hpp"
19#include "private_typeinfo.h"
20#include "include/atomic_support.h"
21
22namespace std
23{
24
25unexpected_handler
26get_unexpected() _NOEXCEPT
27{
28 return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire);
29}
30
31void
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))
40void
41unexpected()
42{
43 __unexpected(get_unexpected());
44}
45
46terminate_handler
47get_terminate() _NOEXCEPT
48{
49 return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire);
50}
51
52void
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))
73void
74terminate() _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
95extern "C" {
96new_handler __cxa_new_handler = 0;
97}
98
99new_handler
100set_new_handler(new_handler handler) _NOEXCEPT
101{
102 return __libcpp_atomic_exchange(&__cxa_new_handler, handler, _AO_Acq_Rel);
103}
104
105new_handler
106get_new_handler() _NOEXCEPT
107{
108 return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
109}
110
111} // std
112