xref: /openbsd-src/gnu/llvm/libcxxabi/src/cxa_handlers.cpp (revision 8f1d572453a8bab44a2fe956e25efc4124e87e82)
1*8f1d5724Srobert //===----------------------------------------------------------------------===//
279c2e3e6Spatrick //
379c2e3e6Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
479c2e3e6Spatrick // See https://llvm.org/LICENSE.txt for license information.
579c2e3e6Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
679c2e3e6Spatrick //
779c2e3e6Spatrick //
879c2e3e6Spatrick // This file implements the functionality associated with the terminate_handler,
979c2e3e6Spatrick // unexpected_handler, and new_handler.
1079c2e3e6Spatrick //===----------------------------------------------------------------------===//
1179c2e3e6Spatrick 
1279c2e3e6Spatrick #include <stdexcept>
1379c2e3e6Spatrick #include <new>
1479c2e3e6Spatrick #include <exception>
1579c2e3e6Spatrick #include "abort_message.h"
1679c2e3e6Spatrick #include "cxxabi.h"
1779c2e3e6Spatrick #include "cxa_handlers.h"
1879c2e3e6Spatrick #include "cxa_exception.h"
1979c2e3e6Spatrick #include "private_typeinfo.h"
20*8f1d5724Srobert #include "include/atomic_support.h" // from libc++
2179c2e3e6Spatrick 
2279c2e3e6Spatrick namespace std
2379c2e3e6Spatrick {
2479c2e3e6Spatrick 
2579c2e3e6Spatrick unexpected_handler
get_unexpected()264e0cc08cSpatrick get_unexpected() noexcept
2779c2e3e6Spatrick {
2879c2e3e6Spatrick     return __libcpp_atomic_load(&__cxa_unexpected_handler, _AO_Acquire);
2979c2e3e6Spatrick }
3079c2e3e6Spatrick 
3179c2e3e6Spatrick void
__unexpected(unexpected_handler func)3279c2e3e6Spatrick __unexpected(unexpected_handler func)
3379c2e3e6Spatrick {
3479c2e3e6Spatrick     func();
3579c2e3e6Spatrick     // unexpected handler should not return
3679c2e3e6Spatrick     abort_message("unexpected_handler unexpectedly returned");
3779c2e3e6Spatrick }
3879c2e3e6Spatrick 
3979c2e3e6Spatrick __attribute__((noreturn))
4079c2e3e6Spatrick void
unexpected()4179c2e3e6Spatrick unexpected()
4279c2e3e6Spatrick {
4379c2e3e6Spatrick     __unexpected(get_unexpected());
4479c2e3e6Spatrick }
4579c2e3e6Spatrick 
4679c2e3e6Spatrick terminate_handler
get_terminate()474e0cc08cSpatrick get_terminate() noexcept
4879c2e3e6Spatrick {
4979c2e3e6Spatrick     return __libcpp_atomic_load(&__cxa_terminate_handler, _AO_Acquire);
5079c2e3e6Spatrick }
5179c2e3e6Spatrick 
5279c2e3e6Spatrick void
__terminate(terminate_handler func)534e0cc08cSpatrick __terminate(terminate_handler func) noexcept
5479c2e3e6Spatrick {
5579c2e3e6Spatrick #ifndef _LIBCXXABI_NO_EXCEPTIONS
5679c2e3e6Spatrick     try
5779c2e3e6Spatrick     {
5879c2e3e6Spatrick #endif // _LIBCXXABI_NO_EXCEPTIONS
5979c2e3e6Spatrick         func();
6079c2e3e6Spatrick         // handler should not return
6179c2e3e6Spatrick         abort_message("terminate_handler unexpectedly returned");
6279c2e3e6Spatrick #ifndef _LIBCXXABI_NO_EXCEPTIONS
6379c2e3e6Spatrick     }
6479c2e3e6Spatrick     catch (...)
6579c2e3e6Spatrick     {
6679c2e3e6Spatrick         // handler should not throw exception
6779c2e3e6Spatrick         abort_message("terminate_handler unexpectedly threw an exception");
6879c2e3e6Spatrick     }
6979c2e3e6Spatrick #endif // _LIBCXXABI_NO_EXCEPTIONS
7079c2e3e6Spatrick }
7179c2e3e6Spatrick 
7279c2e3e6Spatrick __attribute__((noreturn))
7379c2e3e6Spatrick void
terminate()744e0cc08cSpatrick terminate() noexcept
7579c2e3e6Spatrick {
7679c2e3e6Spatrick #ifndef _LIBCXXABI_NO_EXCEPTIONS
7779c2e3e6Spatrick     // If there might be an uncaught exception
7879c2e3e6Spatrick     using namespace __cxxabiv1;
7979c2e3e6Spatrick     __cxa_eh_globals* globals = __cxa_get_globals_fast();
8079c2e3e6Spatrick     if (globals)
8179c2e3e6Spatrick     {
8279c2e3e6Spatrick         __cxa_exception* exception_header = globals->caughtExceptions;
8379c2e3e6Spatrick         if (exception_header)
8479c2e3e6Spatrick         {
8579c2e3e6Spatrick             _Unwind_Exception* unwind_exception =
8679c2e3e6Spatrick                 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
8779c2e3e6Spatrick             if (__isOurExceptionClass(unwind_exception))
8879c2e3e6Spatrick                 __terminate(exception_header->terminateHandler);
8979c2e3e6Spatrick         }
9079c2e3e6Spatrick     }
9179c2e3e6Spatrick #endif
9279c2e3e6Spatrick     __terminate(get_terminate());
9379c2e3e6Spatrick }
9479c2e3e6Spatrick 
9579c2e3e6Spatrick new_handler
get_new_handler()964e0cc08cSpatrick get_new_handler() noexcept
9779c2e3e6Spatrick {
9879c2e3e6Spatrick     return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
9979c2e3e6Spatrick }
10079c2e3e6Spatrick 
10179c2e3e6Spatrick }  // std
102