blob: 26175207ef2b9cde771b03ed3c7d9a328c5f0c02 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#ifndef KUDU_UTIL_DEBUG_UTIL_H
#define KUDU_UTIL_DEBUG_UTIL_H
#include <sys/types.h>
#include <string>
#include <vector>
#include "kudu/gutil/strings/fastmem.h"
#include "kudu/util/status.h"
namespace kudu {
// Return true if coverage is enabled.
bool IsCoverageBuild();
// Try to flush coverage info. If another thread is already flushing
// coverage, this returns without doing anything, since flushing coverage
// is not thread-safe or re-entrant.
void TryFlushCoverage();
// Return a list of all of the thread IDs currently running in this process.
// Not async-safe.
Status ListThreads(std::vector<pid_t>* tids);
// Set which POSIX signal number should be used internally for triggering
// stack traces. If the specified signal handler is already in use, this
// returns an error, and stack traces will be disabled.
Status SetStackTraceSignal(int signum);
// Return the stack trace of the given thread, stringified and symbolized.
//
// Note that the symbolization happens on the calling thread, not the target
// thread, so this is relatively low-impact on the target.
//
// This is safe to use against the current thread, the main thread, or any other
// thread. It requires that the target thread has not blocked POSIX signals. If
// it has, an error message will be returned.
//
// This function is thread-safe but coarsely synchronized: only one "dumper" thread
// may be active at a time.
std::string DumpThreadStack(int64_t tid);
// Return the current stack trace, stringified.
std::string GetStackTrace();
// Return the current stack trace, in hex form. This is significantly
// faster than GetStackTrace() above, so should be used in performance-critical
// places like TRACE() calls. If you really need blazing-fast speed, though,
// use HexStackTraceToString() into a stack-allocated buffer instead --
// this call causes a heap allocation for the std::string.
//
// Note that this is much more useful in the context of a static binary,
// since addr2line wouldn't know where shared libraries were mapped at
// runtime.
//
// NOTE: This inherits the same async-safety issue as HexStackTraceToString()
std::string GetStackTraceHex();
// This is the same as GetStackTraceHex(), except multi-line in a format that
// looks very similar to GetStackTrace() but without symbols. Because it's in
// that format, the tool stacktrace_addr2line.pl in the kudu build-support
// directory can symbolize it automatically (to the extent that addr2line(1)
// is able to find the symbols).
std::string GetLogFormatStackTraceHex();
// Collect the current stack trace in hex form into the given buffer.
//
// The resulting trace just includes the hex addresses, space-separated. This is suitable
// for later stringification by pasting into 'addr2line' for example.
//
// This function is not async-safe, since it uses the libc backtrace() function which
// may invoke the dynamic loader.
void HexStackTraceToString(char* buf, size_t size);
// Efficient class for collecting and later stringifying a stack trace.
//
// Requires external synchronization.
class StackTrace {
public:
StackTrace()
: num_frames_(0) {
}
void Reset() {
num_frames_ = 0;
}
void CopyFrom(const StackTrace& s) {
memcpy(this, &s, sizeof(s));
}
bool Equals(const StackTrace& s) {
return s.num_frames_ == num_frames_ &&
strings::memeq(frames_, s.frames_,
num_frames_ * sizeof(frames_[0]));
}
// Collect and store the current stack trace. Skips the top 'skip_frames' frames
// from the stack. For example, a value of '1' will skip the 'Collect()' function
// call itself.
//
// This function is technically not async-safe. However, according to
// http://lists.nongnu.org/archive/html/libunwind-devel/2011-08/msg00054.html it is "largely
// async safe" and it would only deadlock in the case that you call it while a dynamic library
// load is in progress. We assume that dynamic library loads would almost always be completed
// very early in the application lifecycle, so for now, this is considered "async safe" until
// it proves to be a problem.
void Collect(int skip_frames = 1);
enum Flags {
// Do not fix up the addresses on the stack to try to point to the 'call'
// instructions instead of the return address. This is necessary when dumping
// addresses to be interpreted by 'pprof', which does this fix-up itself.
NO_FIX_CALLER_ADDRESSES = 1
};
// Stringify the trace into the given buffer.
// The resulting output is hex addresses suitable for passing into 'addr2line'
// later.
void StringifyToHex(char* buf, size_t size, int flags = 0) const;
// Same as above, but returning a std::string.
// This is not async-safe.
std::string ToHexString(int flags = 0) const;
// Return a string with a symbolized backtrace in a format suitable for
// printing to a log file.
// This is not async-safe.
std::string Symbolize() const;
// Return a string with a hex-only backtrace in the format typically used in
// log files. Similar to the format given by Symbolize(), but symbols are not
// resolved (only the hex addresses are given).
std::string ToLogFormatHexString() const;
uint64_t HashCode() const;
private:
enum {
// The maximum number of stack frames to collect.
kMaxFrames = 16,
// The max number of characters any frame requires in string form.
kHexEntryLength = 16
};
int num_frames_;
void* frames_[kMaxFrames];
};
} // namespace kudu
#endif