1 // -*- C++ -*- std::terminate, std::unexpected and friends. 2 // Copyright (C) 1994-2020 Free Software Foundation, Inc. 3 // 4 // This file is part of GCC. 5 // 6 // GCC is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 // 11 // GCC is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 #include "typeinfo" 26 #include "exception" 27 #include <cstdlib> 28 #include "unwind-cxx.h" 29 #include "eh_term_handler.h" 30 #include <bits/exception_defines.h> 31 #include <bits/atomic_lockfree_defines.h> 32 33 #if ATOMIC_POINTER_LOCK_FREE < 2 34 #include <ext/concurrence.h> 35 namespace 36 { 37 __gnu_cxx::__mutex mx; 38 } 39 #endif 40 41 using namespace __cxxabiv1; 42 43 void 44 __cxxabiv1::__terminate (std::terminate_handler handler) throw () 45 { 46 __try 47 { 48 handler (); 49 std::abort (); 50 } 51 __catch(...) 52 { std::abort (); } 53 } 54 55 void 56 std::terminate () throw() 57 { 58 __terminate (get_terminate ()); 59 } 60 61 void 62 __cxxabiv1::__unexpected (std::unexpected_handler handler) 63 { 64 handler(); 65 std::terminate (); 66 } 67 68 void 69 std::unexpected () 70 { 71 __unexpected (get_unexpected ()); 72 } 73 74 std::terminate_handler 75 std::set_terminate (std::terminate_handler func) throw() 76 { 77 if (!func) 78 func = _GLIBCXX_DEFAULT_TERM_HANDLER; 79 80 std::terminate_handler old; 81 #if ATOMIC_POINTER_LOCK_FREE > 1 82 __atomic_exchange (&__terminate_handler, &func, &old, __ATOMIC_ACQ_REL); 83 #else 84 __gnu_cxx::__scoped_lock l(mx); 85 old = __terminate_handler; 86 __terminate_handler = func; 87 #endif 88 return old; 89 } 90 91 std::terminate_handler 92 std::get_terminate () noexcept 93 { 94 std::terminate_handler func; 95 #if ATOMIC_POINTER_LOCK_FREE > 1 96 __atomic_load (&__terminate_handler, &func, __ATOMIC_ACQUIRE); 97 #else 98 __gnu_cxx::__scoped_lock l(mx); 99 func = __terminate_handler; 100 #endif 101 return func; 102 } 103 104 std::unexpected_handler 105 std::set_unexpected (std::unexpected_handler func) throw() 106 { 107 if (!func) 108 func = std::terminate; 109 110 std::unexpected_handler old; 111 #if ATOMIC_POINTER_LOCK_FREE > 1 112 __atomic_exchange (&__unexpected_handler, &func, &old, __ATOMIC_ACQ_REL); 113 #else 114 __gnu_cxx::__scoped_lock l(mx); 115 old = __unexpected_handler; 116 __unexpected_handler = func; 117 #endif 118 return old; 119 } 120 121 std::unexpected_handler 122 std::get_unexpected () noexcept 123 { 124 std::unexpected_handler func; 125 #if ATOMIC_POINTER_LOCK_FREE > 1 126 __atomic_load (&__unexpected_handler, &func, __ATOMIC_ACQUIRE); 127 #else 128 __gnu_cxx::__scoped_lock l(mx); 129 func = __unexpected_handler; 130 #endif 131 return func; 132 } 133