Add ability to unwind stack for the current thread
Bug: webrtc:10308 Change-Id: Ia82cb7512524bede8da69bbc747ece6e718733ab Reviewed-on: https://webrtc-review.googlesource.com/c/124993 Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Commit-Queue: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26945}
This commit is contained in:
parent
8b8d01ada3
commit
c130d42aab
@ -164,26 +164,9 @@ const char* CaptureRawStacktrace(int pid,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<StackTraceElement> GetStackTrace(int tid) {
|
||||
// Only a thread itself can unwind its stack, so we will interrupt the given
|
||||
// tid with a custom signal handler in order to unwind its stack. The stack
|
||||
// will be recorded to |params| through the use of the global pointer
|
||||
// |g_signal_handler_param|.
|
||||
SignalHandlerOutputState params;
|
||||
|
||||
const char* error_string = CaptureRawStacktrace(getpid(), tid, ¶ms);
|
||||
if (error_string != nullptr) {
|
||||
RTC_LOG(LS_ERROR) << error_string << ". tid: " << tid
|
||||
<< ". errno: " << errno;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (params.stack_size_counter >= kMaxStackSize)
|
||||
RTC_LOG(LS_WARNING) << "Stack trace for thread " << tid << " was truncated";
|
||||
|
||||
// Translate addresses into symbolic information using dladdr().
|
||||
// Translate addresses into symbolic information using dladdr().
|
||||
std::vector<StackTraceElement> FormatStackTrace(
|
||||
const SignalHandlerOutputState& params) {
|
||||
std::vector<StackTraceElement> stack_trace;
|
||||
for (size_t i = 0; i < params.stack_size_counter; ++i) {
|
||||
const uintptr_t address = params.addresses[i];
|
||||
@ -208,6 +191,36 @@ std::vector<StackTraceElement> GetStackTrace(int tid) {
|
||||
return stack_trace;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::vector<StackTraceElement> GetStackTrace(int tid) {
|
||||
// Only a thread itself can unwind its stack, so we will interrupt the given
|
||||
// tid with a custom signal handler in order to unwind its stack. The stack
|
||||
// will be recorded to |params| through the use of the global pointer
|
||||
// |g_signal_handler_param|.
|
||||
SignalHandlerOutputState params;
|
||||
|
||||
const char* error_string = CaptureRawStacktrace(getpid(), tid, ¶ms);
|
||||
if (error_string != nullptr) {
|
||||
RTC_LOG(LS_ERROR) << error_string << ". tid: " << tid
|
||||
<< ". errno: " << errno;
|
||||
return {};
|
||||
}
|
||||
if (params.stack_size_counter >= kMaxStackSize) {
|
||||
RTC_LOG(LS_WARNING) << "Stack trace for thread " << tid << " was truncated";
|
||||
}
|
||||
return FormatStackTrace(params);
|
||||
}
|
||||
|
||||
std::vector<StackTraceElement> GetStackTrace() {
|
||||
SignalHandlerOutputState params;
|
||||
_Unwind_Backtrace(&UnwindBacktrace, ¶ms);
|
||||
if (params.stack_size_counter >= kMaxStackSize) {
|
||||
RTC_LOG(LS_WARNING) << "Stack trace was truncated";
|
||||
}
|
||||
return FormatStackTrace(params);
|
||||
}
|
||||
|
||||
std::string StackTraceToString(
|
||||
const std::vector<StackTraceElement>& stack_trace) {
|
||||
rtc::StringBuilder string_builder;
|
||||
|
||||
@ -33,6 +33,9 @@ struct StackTraceElement {
|
||||
// on top of unwind.h and unwinds native (C++) stack traces only.
|
||||
std::vector<StackTraceElement> GetStackTrace(int tid);
|
||||
|
||||
// Unwind the stack of the current thread.
|
||||
std::vector<StackTraceElement> GetStackTrace();
|
||||
|
||||
// Get a string representation of the stack trace in a format ndk-stack accepts.
|
||||
std::string StackTraceToString(
|
||||
const std::vector<StackTraceElement>& stack_trace);
|
||||
|
||||
@ -163,6 +163,16 @@ void TestStacktrace(std::unique_ptr<DeadlockInterface> deadlock_impl) {
|
||||
thread.Stop();
|
||||
}
|
||||
|
||||
TEST(Stacktrace, TestCurrentThread) {
|
||||
const uint32_t start_addr = GetCurrentRelativeExecutionAddress();
|
||||
const std::vector<StackTraceElement> stack_trace = GetStackTrace();
|
||||
const uint32_t end_addr = GetCurrentRelativeExecutionAddress();
|
||||
EXPECT_TRUE(StackTraceContainsRange(stack_trace, start_addr, end_addr))
|
||||
<< "Caller region: [" << rtc::ToHex(start_addr) << ", "
|
||||
<< rtc::ToHex(end_addr)
|
||||
<< "] not contained in: " << StackTraceToString(stack_trace);
|
||||
}
|
||||
|
||||
TEST(Stacktrace, TestSpinLock) {
|
||||
TestStacktrace(absl::make_unique<SpinDeadlock>());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user