blob: 46022c457f1c79667857aa9d7adc316a411b9eb7 [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 Hinnantb80931e2011-12-07 21:16:40 +000017#include "cxa_handlers.hpp"
Howard Hinnant44d4d3b2011-12-06 17:51:25 +000018
19namespace std
20{
21
22static const char* cause = "uncaught";
23
24static void default_terminate_handler()
25{
26 std::exception_ptr cp = std::current_exception();
27 if (cp)
28 {
29 try
30 {
31 rethrow_exception(cp);
32 }
33 catch (const std::exception& e)
34 {
35 abort_message("terminating with %s exception: %s\n", cause, e.what());
36 }
37 catch (...)
38 {
39 abort_message("terminating with %s exception\n", cause);
40 }
41 }
42 abort_message("terminating\n");
43}
44
45static void default_unexpected_handler()
46{
47 cause = "unexpected";
48 terminate();
49}
50
51static terminate_handler __terminate_handler = default_terminate_handler;
52static unexpected_handler __unexpected_handler = default_unexpected_handler;
53static new_handler __new_handler = 0;
54
55unexpected_handler
56set_unexpected(unexpected_handler func) _NOEXCEPT
57{
58 if (func == 0)
59 func = default_unexpected_handler;
60 return __sync_lock_test_and_set(&__unexpected_handler, func);
61}
62
63unexpected_handler
64get_unexpected() _NOEXCEPT
65{
66 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
67}
68
69_LIBCPP_HIDDEN
70_ATTRIBUTE(noreturn)
71void
72__unexpected(unexpected_handler func)
73{
74 func();
75 // unexpected handler should not return
76 abort_message("unexpected_handler unexpectedly returned");
77}
78
79_ATTRIBUTE(noreturn)
80void
81unexpected()
82{
83 __unexpected(get_unexpected());
84}
85
86terminate_handler
87set_terminate(terminate_handler func) _NOEXCEPT
88{
89 if (func == 0)
90 func = default_terminate_handler;
91 return __sync_lock_test_and_set(&__terminate_handler, func);
92}
93
94terminate_handler
95get_terminate() _NOEXCEPT
96{
97 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
98}
99
100_LIBCPP_HIDDEN
101_ATTRIBUTE(noreturn)
102void
103__terminate(terminate_handler func) _NOEXCEPT
104{
105#if __has_feature(cxx_exceptions)
106 try
107 {
108#endif // __has_feature(cxx_exceptions)
109 func();
110 // handler should not return
111 abort_message("terminate_handler unexpectedly returned");
112#if __has_feature(cxx_exceptions)
113 }
114 catch (...)
115 {
116 // handler should not throw exception
117 abort_message("terminate_handler unexpectedly threw an exception");
118 }
119#endif // #if __has_feature(cxx_exceptions)
120}
121
122_ATTRIBUTE(noreturn)
123void
124terminate() _NOEXCEPT
125{
126 __terminate(get_terminate());
127}
128
129new_handler
130set_new_handler(new_handler handler) _NOEXCEPT
131{
132 return __sync_lock_test_and_set(&__new_handler, handler);
133}
134
135new_handler
136get_new_handler() _NOEXCEPT
137{
138 return __sync_fetch_and_add(&__new_handler, (new_handler)0);
139}
140
141} // std