blob: 15fde24cd013b80766481cde5406e36c8f1d3a1a [file] [log] [blame]
Howard Hinnant44d4d3b2011-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 Hinnantfe907462012-01-24 18:26:29 +000017#include "cxxabi.h"
Howard Hinnantb80931e2011-12-07 21:16:40 +000018#include "cxa_handlers.hpp"
Howard Hinnantfe907462012-01-24 18:26:29 +000019#include "cxa_exception.hpp"
20#include "private_typeinfo.h"
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000021
22namespace std
23{
24
25static const char* cause = "uncaught";
26
27static void default_terminate_handler()
28{
Howard Hinnantfe907462012-01-24 18:26:29 +000029 // If there might be an uncaught exception
30 using namespace __cxxabiv1;
31 __cxa_eh_globals* globals = __cxa_get_globals_fast();
32 if (globals)
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000033 {
Howard Hinnantfe907462012-01-24 18:26:29 +000034 __cxa_exception* exception_header = globals->caughtExceptions;
35 // If there is an uncaught exception
36 if (exception_header)
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000037 {
Howard Hinnantfe907462012-01-24 18:26:29 +000038 _Unwind_Exception* unwind_exception =
39 reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1;
40 void* thrown_object =
41 unwind_exception->exception_class == kOurDependentExceptionClass ?
42 ((__cxa_dependent_exception*)exception_header)->primaryException :
43 exception_header + 1;
44 const __shim_type_info* thrown_type =
45 static_cast<const __shim_type_info*>(exception_header->exceptionType);
46 const __shim_type_info* catch_type =
47 static_cast<const __shim_type_info*>(&typeid(exception));
48 // If the uncaught exception can be caught with std::exception&
49 if (catch_type->can_catch(thrown_type, thrown_object))
50 {
51 // Include the what() message from the exception
52 const exception* e = static_cast<const exception*>(thrown_object);
53 abort_message("terminating with %s exception: %s", cause, e->what());
54 }
55 else
56 // Else just note that we're terminating with an exception
57 abort_message("terminating with %s exception", cause);
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000058 }
59 }
Howard Hinnantfe907462012-01-24 18:26:29 +000060 // Else just note that we're terminating
61 abort_message("terminating");
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000062}
63
64static void default_unexpected_handler()
65{
66 cause = "unexpected";
67 terminate();
68}
69
70static terminate_handler __terminate_handler = default_terminate_handler;
71static unexpected_handler __unexpected_handler = default_unexpected_handler;
72static new_handler __new_handler = 0;
73
74unexpected_handler
75set_unexpected(unexpected_handler func) _NOEXCEPT
76{
77 if (func == 0)
78 func = default_unexpected_handler;
79 return __sync_lock_test_and_set(&__unexpected_handler, func);
80}
81
82unexpected_handler
83get_unexpected() _NOEXCEPT
84{
85 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
86}
87
Howard Hinnantfe907462012-01-24 18:26:29 +000088__attribute__((visibility("hidden"), noreturn))
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000089void
90__unexpected(unexpected_handler func)
91{
92 func();
93 // unexpected handler should not return
94 abort_message("unexpected_handler unexpectedly returned");
95}
96
Howard Hinnantfe907462012-01-24 18:26:29 +000097__attribute__((noreturn))
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000098void
99unexpected()
100{
101 __unexpected(get_unexpected());
102}
103
104terminate_handler
105set_terminate(terminate_handler func) _NOEXCEPT
106{
107 if (func == 0)
108 func = default_terminate_handler;
109 return __sync_lock_test_and_set(&__terminate_handler, func);
110}
111
112terminate_handler
113get_terminate() _NOEXCEPT
114{
115 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
116}
117
Howard Hinnantfe907462012-01-24 18:26:29 +0000118__attribute__((visibility("hidden"), noreturn))
Howard Hinnant44d4d3b2011-12-06 17:51:25 +0000119void
120__terminate(terminate_handler func) _NOEXCEPT
121{
122#if __has_feature(cxx_exceptions)
123 try
124 {
125#endif // __has_feature(cxx_exceptions)
126 func();
127 // handler should not return
128 abort_message("terminate_handler unexpectedly returned");
129#if __has_feature(cxx_exceptions)
130 }
131 catch (...)
132 {
133 // handler should not throw exception
134 abort_message("terminate_handler unexpectedly threw an exception");
135 }
136#endif // #if __has_feature(cxx_exceptions)
137}
138
Howard Hinnantfe907462012-01-24 18:26:29 +0000139__attribute__((noreturn))
Howard Hinnant44d4d3b2011-12-06 17:51:25 +0000140void
141terminate() _NOEXCEPT
142{
143 __terminate(get_terminate());
144}
145
146new_handler
147set_new_handler(new_handler handler) _NOEXCEPT
148{
149 return __sync_lock_test_and_set(&__new_handler, handler);
150}
151
152new_handler
153get_new_handler() _NOEXCEPT
154{
155 return __sync_fetch_and_add(&__new_handler, (new_handler)0);
156}
157
158} // std