Warning, /include/absl/debugging/internal/stacktrace_generic-inl.inc is written in an unsupported language. File is not indexed.
0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 // https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // Portable implementation - just use glibc
0016 //
0017 // Note: The glibc implementation may cause a call to malloc.
0018 // This can cause a deadlock in HeapProfiler.
0019
0020 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
0021 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
0022
0023 #include <execinfo.h>
0024 #include <atomic>
0025 #include <cstring>
0026
0027 #include "absl/debugging/stacktrace.h"
0028 #include "absl/base/attributes.h"
0029
0030 // Sometimes, we can try to get a stack trace from within a stack
0031 // trace, because we don't block signals inside this code (which would be too
0032 // expensive: the two extra system calls per stack trace do matter here).
0033 // That can cause a self-deadlock.
0034 // Protect against such reentrant call by failing to get a stack trace.
0035 //
0036 // We use __thread here because the code here is extremely low level -- it is
0037 // called while collecting stack traces from within malloc and mmap, and thus
0038 // can not call anything which might call malloc or mmap itself.
0039 static __thread int recursive = 0;
0040
0041 // The stack trace function might be invoked very early in the program's
0042 // execution (e.g. from the very first malloc if using tcmalloc). Also, the
0043 // glibc implementation itself will trigger malloc the first time it is called.
0044 // As such, we suppress usage of backtrace during this early stage of execution.
0045 static std::atomic<bool> disable_stacktraces(true); // Disabled until healthy.
0046 // Waiting until static initializers run seems to be late enough.
0047 // This file is included into stacktrace.cc so this will only run once.
0048 ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {
0049 void* unused_stack[1];
0050 // Force the first backtrace to happen early to get the one-time shared lib
0051 // loading (allocation) out of the way. After the first call it is much safer
0052 // to use backtrace from a signal handler if we crash somewhere later.
0053 backtrace(unused_stack, 1);
0054 disable_stacktraces.store(false, std::memory_order_relaxed);
0055 return 0;
0056 }();
0057
0058 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
0059 static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
0060 const void *ucp, int *min_dropped_frames) {
0061 if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
0062 return 0;
0063 }
0064 ++recursive;
0065
0066 static_cast<void>(ucp); // Unused.
0067 static const int kStackLength = 64;
0068 void * stack[kStackLength];
0069 int size;
0070
0071 size = backtrace(stack, kStackLength);
0072 skip_count++; // we want to skip the current frame as well
0073 int result_count = size - skip_count;
0074 if (result_count < 0)
0075 result_count = 0;
0076 if (result_count > max_depth)
0077 result_count = max_depth;
0078 for (int i = 0; i < result_count; i++)
0079 result[i] = stack[i + skip_count];
0080
0081 if (IS_STACK_FRAMES) {
0082 // No implementation for finding out the stack frame sizes yet.
0083 memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));
0084 }
0085 if (min_dropped_frames != nullptr) {
0086 if (size - skip_count - max_depth > 0) {
0087 *min_dropped_frames = size - skip_count - max_depth;
0088 } else {
0089 *min_dropped_frames = 0;
0090 }
0091 }
0092
0093 --recursive;
0094
0095 return result_count;
0096 }
0097
0098 namespace absl {
0099 ABSL_NAMESPACE_BEGIN
0100 namespace debugging_internal {
0101 bool StackTraceWorksForTest() {
0102 return true;
0103 }
0104 } // namespace debugging_internal
0105 ABSL_NAMESPACE_END
0106 } // namespace absl
0107
0108 #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_