1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Let's run ForcedUnwind until it reaches end of the stack, this test simulates 10 // what pthread_cancel does. 11 12 // UNSUPPORTED: c++03 13 // UNSUPPORTED: libcxxabi-no-threads 14 // UNSUPPORTED: no-exceptions 15 16 #include <assert.h> 17 #include <exception> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unwind.h> 21 #include <thread> 22 #include <tuple> 23 #include <__cxxabi_config.h> 24 25 // TODO: dump version back to 14 once clang is updated on the CI. 26 #if defined(_LIBCXXABI_ARM_EHABI) && defined(__clang__) && __clang_major__ < 15 27 // _Unwind_ForcedUnwind is not available or broken before version 14. 28 int main(int, char**) { return 0; } 29 30 #else 31 static bool destructorCalled = false; 32 33 struct myClass { 34 myClass() {} 35 ~myClass() { 36 assert(destructorCalled == false); 37 destructorCalled = true; 38 }; 39 }; 40 41 template <typename T> 42 struct Stop; 43 44 template <typename R, typename... Args> 45 struct Stop<R (*)(Args...)> { 46 // The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM 47 // libunwind while _Unwind_Exception_Class in libgcc. 48 typedef typename std::tuple_element<2, std::tuple<Args...>>::type type; 49 50 static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type, struct _Unwind_Exception*, struct _Unwind_Context*, 51 void*) { 52 if (actions & _UA_END_OF_STACK) { 53 assert(destructorCalled == true); 54 exit(0); 55 } 56 return _URC_NO_REASON; 57 } 58 }; 59 60 static void forced_unwind() { 61 _Unwind_Exception* exc = new _Unwind_Exception; 62 memset(&exc->exception_class, 0, sizeof(exc->exception_class)); 63 exc->exception_cleanup = 0; 64 _Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0); 65 abort(); 66 } 67 68 __attribute__((__noinline__)) static void test() { 69 myClass c{}; 70 forced_unwind(); 71 abort(); 72 } 73 74 int main(int, char**) { 75 std::thread t{test}; 76 t.join(); 77 return -1; 78 } 79 #endif 80