X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fexperimental%2Fexception_tracer%2FExceptionTracerLib.cpp;h=d4a8fa152783187087ceea69ed4fcd32a5e88610;hp=788898212a4ce8bf0096f46d37a3bcf842e9ca3d;hb=3680f888411a4eea23aae712149932f4bb37d349;hpb=d8c1a8c069f29498ea6db6094837042c2744913a diff --git a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp index 78889821..d4a8fa15 100644 --- a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp +++ b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012 Facebook, Inc. + * Copyright 2013 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,50 +14,56 @@ * limitations under the License. */ - #include #include #include #include +#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)); +typedef void (*CxaThrowType)(void*, std::type_info*, void (*)(void)) + FOLLY_NORETURN; typedef void* (*CxaBeginCatchType)(void*); -typedef void (*CxaRethrowType)(void); +typedef void (*CxaRethrowType)(void) + FOLLY_NORETURN; typedef void (*CxaEndCatchType)(void); -CxaThrowType orig_cxa_throw __attribute__((noreturn)); +CxaThrowType orig_cxa_throw; CxaBeginCatchType orig_cxa_begin_catch; -CxaRethrowType orig_cxa_rethrow __attribute__((noreturn)); +CxaRethrowType orig_cxa_rethrow; CxaEndCatchType orig_cxa_end_catch; } // extern "C" -typedef void (*RethrowExceptionType)(std::exception_ptr); -RethrowExceptionType orig_rethrow_exception __attribute__((noreturn)); +typedef void (*RethrowExceptionType)(std::exception_ptr) + FOLLY_NORETURN; +RethrowExceptionType orig_rethrow_exception; void initialize() { orig_cxa_throw = (CxaThrowType)dlsym(RTLD_NEXT, "__cxa_throw"); @@ -83,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; } } @@ -131,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); } @@ -150,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();