1//===----------------------------------------------------------------------===//
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" // from libc++
21
22namespace std
23{
24
25unexpected_handler
26get_unexpected() noexcept
27{
28 return __libcpp_atomic_load(val: &__cxa_unexpected_handler, order: _AO_Acquire);
29}
30
31void
32__unexpected(unexpected_handler func)
33{
34 func();
35 // unexpected handler should not return
36 __abort_message(format: "unexpected_handler unexpectedly returned");
37}
38
39[[noreturn]] void
40unexpected()
41{
42 __unexpected(func: get_unexpected());
43}
44
45terminate_handler
46get_terminate() noexcept
47{
48 return __libcpp_atomic_load(val: &__cxa_terminate_handler, order: _AO_Acquire);
49}
50
51void
52__terminate(terminate_handler func) noexcept
53{
54#ifndef _LIBCXXABI_NO_EXCEPTIONS
55 try
56 {
57#endif // _LIBCXXABI_NO_EXCEPTIONS
58 func();
59 // handler should not return
60 __abort_message(format: "terminate_handler unexpectedly returned");
61#ifndef _LIBCXXABI_NO_EXCEPTIONS
62 }
63 catch (...)
64 {
65 // handler should not throw exception
66 __abort_message(format: "terminate_handler unexpectedly threw an exception");
67 }
68#endif // _LIBCXXABI_NO_EXCEPTIONS
69}
70
71[[noreturn]] void
72terminate() noexcept
73{
74#ifndef _LIBCXXABI_NO_EXCEPTIONS
75 // If there might be an uncaught exception
76 using namespace __cxxabiv1;
77 __cxa_eh_globals* globals = __cxa_get_globals_fast();
78 if (globals)
79 {
80 __cxa_exception* exception_header = globals->caughtExceptions;
81 if (exception_header)
82 {
83 _Unwind_Exception* unwind_exception =
84 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
85 if (__isOurExceptionClass(unwind_exception))
86 __terminate(func: exception_header->terminateHandler);
87 }
88 }
89#endif
90 __terminate(func: get_terminate());
91}
92
93new_handler
94get_new_handler() noexcept
95{
96 return __libcpp_atomic_load(val: &__cxa_new_handler, order: _AO_Acquire);
97}
98
99} // std
100