summaryrefslogtreecommitdiffstats
path: root/base/debug/stack_trace_posix.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/debug/stack_trace_posix.cc')
-rw-r--r--base/debug/stack_trace_posix.cc79
1 files changed, 79 insertions, 0 deletions
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc
index aef80b3..ff756fc0 100644
--- a/base/debug/stack_trace_posix.cc
+++ b/base/debug/stack_trace_posix.cc
@@ -7,6 +7,7 @@
#include <errno.h>
#include <execinfo.h>
#include <fcntl.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
@@ -145,8 +146,86 @@ bool GetBacktraceStrings(void *const *trace, int size,
return symbolized;
}
+void StackDumpSignalHandler(int signal, siginfo_t* info, ucontext_t* context) {
+ if (BeingDebugged())
+ BreakDebugger();
+
+#if defined(OS_MACOSX)
+ // TODO(phajdan.jr): Fix async-signal non-safety (http://crbug.com/101155).
+ DLOG(ERROR) << "Received signal " << signal;
+ StackTrace().PrintBacktrace();
+#endif
+
+ // TODO(shess): Port to Linux.
+#if defined(OS_MACOSX)
+ // TODO(shess): Port to 64-bit.
+#if ARCH_CPU_X86_FAMILY && ARCH_CPU_32_BITS
+ char buf[1024];
+ size_t len;
+
+ // NOTE: Even |snprintf()| is not on the approved list for signal
+ // handlers, but buffered I/O is definitely not on the list due to
+ // potential for |malloc()|.
+ len = static_cast<size_t>(
+ snprintf(buf, sizeof(buf),
+ "ax: %x, bx: %x, cx: %x, dx: %x\n",
+ context->uc_mcontext->__ss.__eax,
+ context->uc_mcontext->__ss.__ebx,
+ context->uc_mcontext->__ss.__ecx,
+ context->uc_mcontext->__ss.__edx));
+ write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
+
+ len = static_cast<size_t>(
+ snprintf(buf, sizeof(buf),
+ "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n",
+ context->uc_mcontext->__ss.__edi,
+ context->uc_mcontext->__ss.__esi,
+ context->uc_mcontext->__ss.__ebp,
+ context->uc_mcontext->__ss.__esp,
+ context->uc_mcontext->__ss.__ss,
+ context->uc_mcontext->__ss.__eflags));
+ write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
+
+ len = static_cast<size_t>(
+ snprintf(buf, sizeof(buf),
+ "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n",
+ context->uc_mcontext->__ss.__eip,
+ context->uc_mcontext->__ss.__cs,
+ context->uc_mcontext->__ss.__ds,
+ context->uc_mcontext->__ss.__es,
+ context->uc_mcontext->__ss.__fs,
+ context->uc_mcontext->__ss.__gs));
+ write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
+#endif // ARCH_CPU_32_BITS
+#endif // defined(OS_MACOSX)
+ _exit(1);
+}
+
} // namespace
+#if !defined(OS_IOS)
+bool EnableInProcessStackDumping() {
+ // When running in an application, our code typically expects SIGPIPE
+ // to be ignored. Therefore, when testing that same code, it should run
+ // with SIGPIPE ignored as well.
+ struct sigaction action;
+ memset(&action, 0, sizeof(action));
+ action.sa_handler = SIG_IGN;
+ sigemptyset(&action.sa_mask);
+ bool success = (sigaction(SIGPIPE, &action, NULL) == 0);
+
+ sig_t handler = reinterpret_cast<sig_t>(&StackDumpSignalHandler);
+ success &= (signal(SIGILL, handler) != SIG_ERR);
+ success &= (signal(SIGABRT, handler) != SIG_ERR);
+ success &= (signal(SIGFPE, handler) != SIG_ERR);
+ success &= (signal(SIGBUS, handler) != SIG_ERR);
+ success &= (signal(SIGSEGV, handler) != SIG_ERR);
+ success &= (signal(SIGSYS, handler) != SIG_ERR);
+
+ return success;
+}
+#endif // !defined(OS_IOS)
+
StackTrace::StackTrace() {
// Though the backtrace API man page does not list any possible negative
// return values, we take no chance.