cxa_handlers.cpp revision 439ce87946c310a093f4d39a2636ce6b4682bdac
1//===------------------------- 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"
17#include "cxxabi.h"
18#include "cxa_handlers.hpp"
19#include "cxa_exception.hpp"
20#include "cxa_default_handlers.hpp"
21#include "private_typeinfo.h"
22
23namespace std
24{
25
26
27unexpected_handler
28set_unexpected(unexpected_handler func) _NOEXCEPT
29{
30    if (func == 0)
31        func = default_unexpected_handler;
32    return __sync_lock_test_and_set(&__cxxabiapple::__cxa_unexpected_handler, func);
33}
34
35unexpected_handler
36get_unexpected() _NOEXCEPT
37{
38    return __sync_fetch_and_add(&__cxxabiapple::__cxa_unexpected_handler, (unexpected_handler)0);
39}
40
41__attribute__((visibility("hidden"), noreturn))
42void
43__unexpected(unexpected_handler func)
44{
45    func();
46    // unexpected handler should not return
47    abort_message("unexpected_handler unexpectedly returned");
48}
49
50__attribute__((noreturn))
51void
52unexpected()
53{
54    __unexpected(get_unexpected());
55}
56
57terminate_handler
58set_terminate(terminate_handler func) _NOEXCEPT
59{
60    if (func == 0)
61        func = default_terminate_handler;
62    return __sync_lock_test_and_set(&__cxxabiapple::__cxa_terminate_handler, func);
63}
64
65terminate_handler
66get_terminate() _NOEXCEPT
67{
68    return __sync_fetch_and_add(&__cxxabiapple::__cxa_terminate_handler, (terminate_handler)0);
69}
70
71__attribute__((visibility("hidden"), noreturn))
72void
73__terminate(terminate_handler func) _NOEXCEPT
74{
75#if __has_feature(cxx_exceptions)
76    try
77    {
78#endif  // __has_feature(cxx_exceptions)
79        func();
80        // handler should not return
81        abort_message("terminate_handler unexpectedly returned");
82#if __has_feature(cxx_exceptions)
83    }
84    catch (...)
85    {
86        // handler should not throw exception
87        abort_message("terminate_handler unexpectedly threw an exception");
88    }
89#endif  // #if __has_feature(cxx_exceptions)
90}
91
92__attribute__((noreturn))
93void
94terminate() _NOEXCEPT
95{
96    // If there might be an uncaught exception
97    using namespace __cxxabiv1;
98    __cxa_eh_globals* globals = __cxa_get_globals_fast();
99    if (globals)
100    {
101        __cxa_exception* exception_header = globals->caughtExceptions;
102        if (exception_header)
103        {
104            _Unwind_Exception* unwind_exception =
105                reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
106            bool native_exception =
107                (unwind_exception->exception_class & get_vendor_and_language) ==
108                               (kOurExceptionClass & get_vendor_and_language);
109            if (native_exception)
110                __terminate(exception_header->terminateHandler);
111        }
112    }
113    __terminate(get_terminate());
114}
115
116new_handler
117set_new_handler(new_handler handler) _NOEXCEPT
118{
119    return __sync_lock_test_and_set(&__cxxabiapple::__cxa_new_handler, handler);
120}
121
122new_handler
123get_new_handler() _NOEXCEPT
124{
125    return __sync_fetch_and_add(&__cxxabiapple::__cxa_new_handler, (new_handler)0);
126}
127
128}  // std
129