Use fixed size stack traces; unify getStackTrace
[folly.git] / folly / experimental / exception_tracer / ExceptionTracerLib.cpp
index 2a7c954b8619c04011088e4e5e5bb97023d71d79..d4a8fa152783187087ceea69ed4fcd32a5e88610 100644 (file)
 
 #include <glog/logging.h>
 
+#include "folly/Portability.h"
 #include "folly/experimental/exception_tracer/StackTrace.h"
 #include "folly/experimental/exception_tracer/ExceptionAbi.h"
 #include "folly/experimental/exception_tracer/ExceptionTracer.h"
+#include "folly/experimental/symbolizer/Symbolizer.h"
 
 namespace __cxxabiv1 {
 
 extern "C" {
 void __cxa_throw(void* thrownException, std::type_info* type,
-                 void (*destructor)(void)) __attribute__((noreturn));
+                 void (*destructor)(void)) FOLLY_NORETURN;
 void* __cxa_begin_catch(void* excObj);
-void __cxa_rethrow(void) __attribute__((noreturn));
+void __cxa_rethrow(void) FOLLY_NORETURN;
 void __cxa_end_catch(void);
 }
 
 }  // namespace __cxxabiv1
 
+using namespace folly::exception_tracer;
+
 namespace {
 
 __thread bool invalid;
-__thread StackTraceStack* activeExceptions;
-__thread StackTraceStack* caughtExceptions;
+__thread StackTraceStack activeExceptions;
+__thread StackTraceStack caughtExceptions;
 pthread_once_t initialized = PTHREAD_ONCE_INIT;
 
 extern "C" {
 typedef void (*CxaThrowType)(void*, std::type_info*, void (*)(void))
-  __attribute__((noreturn));
+  FOLLY_NORETURN;
 typedef void* (*CxaBeginCatchType)(void*);
 typedef void (*CxaRethrowType)(void)
-  __attribute__((noreturn));
+  FOLLY_NORETURN;
 typedef void (*CxaEndCatchType)(void);
 
 CxaThrowType orig_cxa_throw;
@@ -58,7 +62,7 @@ CxaEndCatchType orig_cxa_end_catch;
 }  // extern "C"
 
 typedef void (*RethrowExceptionType)(std::exception_ptr)
-  __attribute__((noreturn));
+  FOLLY_NORETURN;
 RethrowExceptionType orig_rethrow_exception;
 
 void initialize() {
@@ -85,34 +89,34 @@ void initialize() {
 }  // namespace
 
 // This function is exported and may be found via dlsym(RTLD_NEXT, ...)
-extern "C" const StackTraceStack* getExceptionStackTraceStack() {
-  return caughtExceptions;
+extern "C" StackTraceStack* getExceptionStackTraceStack() {
+  return invalid ? nullptr : &caughtExceptions;
 }
 
 namespace {
-// Make sure we're counting stack frames correctly for the "skip" argument to
-// pushCurrentStackTrace, don't inline.
+
+// Make sure we're counting stack frames correctly, don't inline.
 void addActiveException() __attribute__((noinline));
 
 void addActiveException() {
   pthread_once(&initialized, initialize);
   // Capture stack trace
   if (!invalid) {
-    if (pushCurrentStackTrace(3, &activeExceptions) != 0) {
-      clearStack(&activeExceptions);
-      clearStack(&caughtExceptions);
+    if (!activeExceptions.pushCurrent()) {
+      activeExceptions.clear();
+      caughtExceptions.clear();
       invalid = true;
     }
   }
 }
 
-void moveTopException(StackTraceStack** from, StackTraceStack** to) {
+void moveTopException(StackTraceStack& from, StackTraceStack& to) {
   if (invalid) {
     return;
   }
-  if (moveTop(from, to) != 0) {
-    clearStack(from);
-    clearStack(to);
+  if (!to.moveTopFrom(from)) {
+    from.clear();
+    to.clear();
     invalid = true;
   }
 }
@@ -133,13 +137,13 @@ void __cxa_rethrow() {
   // we'll implement something simpler (and slower): we pop the exception from
   // the caught stack, and push it back onto the active stack; this way, our
   // implementation of __cxa_begin_catch doesn't have to do anything special.
-  moveTopException(&caughtExceptions, &activeExceptions);
+  moveTopException(caughtExceptions, activeExceptions);
   orig_cxa_rethrow();
 }
 
 void* __cxa_begin_catch(void *excObj) {
   // excObj is a pointer to the unwindHeader in __cxa_exception
-  moveTopException(&activeExceptions, &caughtExceptions);
+  moveTopException(activeExceptions, caughtExceptions);
   return orig_cxa_begin_catch(excObj);
 }
 
@@ -152,7 +156,10 @@ void __cxa_end_catch() {
     // In the rethrow case, we've already popped the exception off the
     // caught stack, so we don't do anything here.
     if (top->handlerCount == 1) {
-      popStackTrace(&caughtExceptions);
+      if (!caughtExceptions.pop()) {
+        activeExceptions.clear();
+        invalid = true;
+      }
     }
   }
   orig_cxa_end_catch();