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