blob: 2881a2a65fec9e8d2997f3f5b1a904a49266ee97 [file] [log] [blame]
Howard Hinnantd2af0fd2011-12-06 17:51:25 +00001//===------------------------- cxa_handlers.cpp ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// This file implements the functionality associated with the terminate_handler,
10// unexpected_handler, and new_handler.
11//===----------------------------------------------------------------------===//
12
13#include <stdexcept>
14#include <new>
15#include <exception>
16#include "abort_message.h"
Howard Hinnant3f034b72012-01-24 18:26:29 +000017#include "cxxabi.h"
Howard Hinnante8fcf832011-12-07 21:16:40 +000018#include "cxa_handlers.hpp"
Howard Hinnant3f034b72012-01-24 18:26:29 +000019#include "cxa_exception.hpp"
20#include "private_typeinfo.h"
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000021
22namespace std
23{
24
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000025unexpected_handler
26get_unexpected() _NOEXCEPT
27{
Howard Hinnant4cfb63f2012-03-19 16:56:51 +000028 return __sync_fetch_and_add(&__cxa_unexpected_handler, (unexpected_handler)0);
29// The above is safe but overkill on x86
30// Using of C++11 atomics this should be rewritten
31// return __cxa_unexpected_handler.load(memory_order_acq);
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000032}
33
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000034void
35__unexpected(unexpected_handler func)
36{
37 func();
38 // unexpected handler should not return
39 abort_message("unexpected_handler unexpectedly returned");
40}
41
Howard Hinnant3f034b72012-01-24 18:26:29 +000042__attribute__((noreturn))
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000043void
44unexpected()
45{
46 __unexpected(get_unexpected());
47}
48
49terminate_handler
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000050get_terminate() _NOEXCEPT
51{
Howard Hinnant4cfb63f2012-03-19 16:56:51 +000052 return __sync_fetch_and_add(&__cxa_terminate_handler, (terminate_handler)0);
53// The above is safe but overkill on x86
54// Using of C++11 atomics this should be rewritten
55// return __cxa_terminate_handler.load(memory_order_acq);
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000056}
57
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000058void
59__terminate(terminate_handler func) _NOEXCEPT
60{
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000061#ifndef _LIBCXXABI_NO_EXCEPTIONS
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000062 try
63 {
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000064#endif // _LIBCXXABI_NO_EXCEPTIONS
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000065 func();
66 // handler should not return
67 abort_message("terminate_handler unexpectedly returned");
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000068#ifndef _LIBCXXABI_NO_EXCEPTIONS
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000069 }
70 catch (...)
71 {
72 // handler should not throw exception
73 abort_message("terminate_handler unexpectedly threw an exception");
74 }
Asiri Rathnayake4174e8b2016-05-31 12:01:32 +000075#endif // _LIBCXXABI_NO_EXCEPTIONS
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000076}
77
Howard Hinnant3f034b72012-01-24 18:26:29 +000078__attribute__((noreturn))
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000079void
80terminate() _NOEXCEPT
81{
Howard Hinnant1a584912012-01-31 01:51:15 +000082 // If there might be an uncaught exception
83 using namespace __cxxabiv1;
84 __cxa_eh_globals* globals = __cxa_get_globals_fast();
85 if (globals)
86 {
87 __cxa_exception* exception_header = globals->caughtExceptions;
88 if (exception_header)
89 {
90 _Unwind_Exception* unwind_exception =
91 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
Howard Hinnant7ab185e2012-02-01 18:15:15 +000092 bool native_exception =
93 (unwind_exception->exception_class & get_vendor_and_language) ==
94 (kOurExceptionClass & get_vendor_and_language);
Howard Hinnant1a584912012-01-31 01:51:15 +000095 if (native_exception)
Howard Hinnant1a584912012-01-31 01:51:15 +000096 __terminate(exception_header->terminateHandler);
Howard Hinnant1a584912012-01-31 01:51:15 +000097 }
98 }
Howard Hinnantd2af0fd2011-12-06 17:51:25 +000099 __terminate(get_terminate());
100}
101
Saleem Abdulrasool436072f2016-05-26 02:12:20 +0000102// In the future this will become:
Howard Hinnant4cfb63f2012-03-19 16:56:51 +0000103// std::atomic<std::new_handler> __cxa_new_handler(0);
Saleem Abdulrasool3eacb7e2017-01-04 05:45:24 +0000104extern "C" {
Shoaib Meenai54227ae2017-03-01 03:55:57 +0000105new_handler __cxa_new_handler = 0;
Saleem Abdulrasool3eacb7e2017-01-04 05:45:24 +0000106}
Howard Hinnant0f80bb72012-03-19 16:20:34 +0000107
Howard Hinnantd2af0fd2011-12-06 17:51:25 +0000108new_handler
109set_new_handler(new_handler handler) _NOEXCEPT
110{
Reid Kleckner5660f752014-10-03 20:03:47 +0000111 return __atomic_exchange_n(&__cxa_new_handler, handler, __ATOMIC_ACQ_REL);
Howard Hinnant4cfb63f2012-03-19 16:56:51 +0000112// Using of C++11 atomics this should be rewritten
113// return __cxa_new_handler.exchange(handler, memory_order_acq_rel);
Howard Hinnantd2af0fd2011-12-06 17:51:25 +0000114}
115
116new_handler
117get_new_handler() _NOEXCEPT
118{
Howard Hinnant4cfb63f2012-03-19 16:56:51 +0000119 return __sync_fetch_and_add(&__cxa_new_handler, (new_handler)0);
120// The above is safe but overkill on x86
121// Using of C++11 atomics this should be rewritten
122// return __cxa_new_handler.load(memory_order_acq);
Howard Hinnantd2af0fd2011-12-06 17:51:25 +0000123}
124
125} // std