proxygen
ExceptionStackTraceLib.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <exception>
18 
24 
25 using namespace folly::exception_tracer;
26 
27 namespace {
28 
29 // If we somehow ended up in an invalid state, we don't want to print any stack
30 // trace at all because in could be bogus
31 FOLLY_TLS bool invalid;
32 
33 FOLLY_TLS StackTraceStack activeExceptions;
34 FOLLY_TLS StackTraceStack caughtExceptions;
35 
36 } // namespace
37 
38 // This function is exported and may be found via dlsym(RTLD_NEXT, ...)
40  return invalid ? nullptr : &caughtExceptions;
41 }
42 
43 namespace {
44 
45 void addActiveException() {
46  // Capture stack trace
47  if (!invalid) {
48  if (!activeExceptions.pushCurrent()) {
49  activeExceptions.clear();
50  caughtExceptions.clear();
51  invalid = true;
52  }
53  }
54 }
55 
56 void moveTopException(StackTraceStack& from, StackTraceStack& to) {
57  if (invalid) {
58  return;
59  }
60  if (!to.moveTopFrom(from)) {
61  from.clear();
62  to.clear();
63  invalid = true;
64  }
65 }
66 
67 struct Initializer {
68  Initializer() {
70  [](void*, std::type_info*, void (*)(void*)) noexcept {
71  addActiveException();
72  });
73 
75  moveTopException(activeExceptions, caughtExceptions);
76  });
77 
79  moveTopException(caughtExceptions, activeExceptions);
80  });
81 
83  if (invalid) {
84  return;
85  }
86 
89  // This is gcc specific and not specified in the ABI:
90  // abs(handlerCount) is the number of active handlers, it's negative
91  // for rethrown exceptions and positive (always 1) for regular
92  // exceptions.
93  // In the rethrow case, we've already popped the exception off the
94  // caught stack, so we don't do anything here.
95  // For Lua interop, we see the handlerCount = 0
96  if ((top->handlerCount == 1) || (top->handlerCount == 0)) {
97  if (!caughtExceptions.pop()) {
98  activeExceptions.clear();
99  invalid = true;
100  }
101  }
102  });
103 
105  [](std::exception_ptr) noexcept { addActiveException(); });
106 
107  try {
109  } catch (...) {
110  }
111  }
112 };
113 
114 Initializer initializer;
115 
116 } // namespace
void registerCxaThrowCallback(CxaThrowType callback)
requires E e noexcept(noexcept(s.error(std::move(e))))
void registerCxaBeginCatchCallback(CxaBeginCatchType callback)
std::enable_if< detail::is_chrono_conversion< Tgt, Src >::value, Tgt >::type to(const Src &value)
Definition: Conv.h:677
void registerCxaEndCatchCallback(CxaEndCatchType callback)
StackTraceStack * getExceptionStackTraceStack()
__cxa_eh_globals * __cxa_get_globals_fast(void) noexcept
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::operators::from_fn from
PUSHMI_INLINE_VAR constexpr __adl::get_top_fn top
__cxa_exception * caughtExceptions
Definition: ExceptionAbi.h:47
void registerCxaRethrowCallback(CxaRethrowType callback)
bool moveTopFrom(StackTraceStack &other)
Definition: StackTrace.cpp:81
void registerRethrowExceptionCallback(RethrowExceptionType callback)