master
  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(&__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
 95new_handler
 96get_new_handler() noexcept
 97{
 98    return __libcpp_atomic_load(&__cxa_new_handler, _AO_Acquire);
 99}
100
101}  // std