Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1678)

Unified Diff: base/debug/stack_trace.cc

Issue 1975393002: Check stack pointer to be inside stack when unwinding. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix renderer deadlock on Linux Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/debug/stack_trace.cc
diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc
index 1c96a569d9795544231714f0d0b1f9b0da036355..9ad2e9fd45b2552e979df72659f8b361bf1c5fcf 100644
--- a/base/debug/stack_trace.cc
+++ b/base/debug/stack_trace.cc
@@ -11,6 +11,18 @@
#include "base/macros.h"
+// TODO(dskiba): use blink::StackFrameDepth::getStackStart() instead
+#if HAVE_TRACE_STACK_FRAME_POINTERS && \
+ (defined(OS_ANDROID) || defined(OS_LINUX))
+#define HAVE_STACK_START
+#include <pthread.h>
+#if defined(__GLIBC__)
+#include "base/process/process_handle.h"
+#include "base/threading/platform_thread.h"
+extern "C" void* __libc_stack_end; // NOLINT
+#endif
+#endif
+
namespace base {
namespace debug {
@@ -41,14 +53,52 @@ std::string StackTrace::ToString() const {
#if HAVE_TRACE_STACK_FRAME_POINTERS
+#if defined(HAVE_STACK_START)
+
+static uintptr_t GetStackStart() {
+#if defined(__GLIBC__)
+ if (GetCurrentProcId() == PlatformThread::CurrentId()) {
+ // Calling pthread_getattr_np() on the main thread sometimes fails,
+ // and also causes reentrancy deadlock in the renderer.
+ return reinterpret_cast<uintptr_t>(__libc_stack_end);
+ }
+#endif
+
+ uintptr_t stack_base = 0;
+ size_t stack_size = 0;
+ pthread_attr_t attributes;
+ int error = pthread_getattr_np(pthread_self(), &attributes);
+ if (!error) {
+ error = pthread_attr_getstack(
+ &attributes,
+ reinterpret_cast<void**>(&stack_base),
+ &stack_size);
+ pthread_attr_destroy(&attributes);
+ }
+ CHECK(!error);
mmenke 2016/05/27 17:39:43 include base/logging.h
+
+ return stack_base + stack_size;
+}
+
+#endif // HAVE_STACK_START
+
+PerThreadStackInfo::PerThreadStackInfo(): start_address(0) {}
+
size_t TraceStackFramePointers(const void** out_trace,
size_t max_depth,
- size_t skip_initial) {
+ size_t skip_initial,
+ PerThreadStackInfo* stack_info) {
// Usage of __builtin_frame_address() enables frame pointers in this
// function even if they are not enabled globally. So 'sp' will always
// be valid.
uintptr_t sp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
+#if defined(HAVE_STACK_START)
+ if (stack_info && !stack_info->start_address) {
+ stack_info->start_address = GetStackStart();
+ }
+#endif
+
size_t depth = 0;
while (depth < max_depth) {
#if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
@@ -58,6 +108,15 @@ size_t TraceStackFramePointers(const void** out_trace,
sp -= sizeof(uintptr_t);
#endif
+#if defined(HAVE_STACK_START)
+ // Both sp[0] and s[1] must be valid. Note that since the stack
+ // is growing downwards, 'start_address' is the highest valid address.
+ if (stack_info &&
+ sp + 2 * sizeof(uintptr_t) > stack_info->start_address) {
+ break;
+ }
+#endif
+
if (skip_initial != 0) {
skip_initial--;
} else {

Powered by Google App Engine
This is Rietveld 408576698