Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libunwind][ARM] Handle end of stack during unwind
When unwind step reaches the end of the stack that means the force unwind should notify the stop function. This is not an error, it could mean just the thread is cleaned up completely. Reviewed By: #libunwind, mstorsjo Differential Revision: https://reviews.llvm.org/D109856
- Loading branch information
1 parent
8967d04
commit 632acec
Showing
3 changed files
with
110 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// Let's run ForcedUnwind until it reaches end of the stack, this test simulates | ||
// what pthread_cancel does. | ||
|
||
// UNSUPPORTED: c++03 | ||
// UNSUPPORTED: libcxxabi-no-threads | ||
// UNSUPPORTED: no-exceptions | ||
|
||
#include <assert.h> | ||
#include <exception> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unwind.h> | ||
#include <thread> | ||
#include <tuple> | ||
#include <__cxxabi_config.h> | ||
|
||
// TODO: dump version back to 14 once clang is updated on the CI. | ||
#if defined(_LIBCXXABI_ARM_EHABI) && defined(__clang__) && __clang_major__ < 15 | ||
// _Unwind_ForcedUnwind is not available or broken before version 14. | ||
int main(int, char**) { return 0; } | ||
|
||
#else | ||
static bool destructorCalled = false; | ||
|
||
struct myClass { | ||
myClass() {} | ||
~myClass() { | ||
assert(destructorCalled == false); | ||
destructorCalled = true; | ||
}; | ||
}; | ||
|
||
template <typename T> | ||
struct Stop; | ||
|
||
template <typename R, typename... Args> | ||
struct Stop<R (*)(Args...)> { | ||
// The third argument of _Unwind_Stop_Fn is uint64_t in Itanium C++ ABI/LLVM | ||
// libunwind while _Unwind_Exception_Class in libgcc. | ||
typedef typename std::tuple_element<2, std::tuple<Args...>>::type type; | ||
|
||
static _Unwind_Reason_Code stop(int, _Unwind_Action actions, type, struct _Unwind_Exception*, struct _Unwind_Context*, | ||
void*) { | ||
if (actions & _UA_END_OF_STACK) { | ||
assert(destructorCalled == true); | ||
exit(0); | ||
} | ||
return _URC_NO_REASON; | ||
} | ||
}; | ||
|
||
static void forced_unwind() { | ||
_Unwind_Exception* exc = new _Unwind_Exception; | ||
memset(&exc->exception_class, 0, sizeof(exc->exception_class)); | ||
exc->exception_cleanup = 0; | ||
_Unwind_ForcedUnwind(exc, Stop<_Unwind_Stop_Fn>::stop, 0); | ||
abort(); | ||
} | ||
|
||
__attribute__((__noinline__)) static void test() { | ||
myClass c{}; | ||
forced_unwind(); | ||
abort(); | ||
} | ||
|
||
int main(int, char**) { | ||
std::thread t{test}; | ||
t.join(); | ||
return -1; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters