mirror of
https://github.com/ceph/ceph
synced 2025-03-06 00:10:04 +00:00
Merge pull request #9028 from tchaikov/wip-bt-dump
common/BackTrace: add operator<< Reviewed-by: Brad Hubbard <bhubbard@redhat.com>
This commit is contained in:
commit
c3aed5cdf9
@ -14,7 +14,7 @@
|
||||
|
||||
namespace ceph {
|
||||
|
||||
void BackTrace::print(std::ostream& out)
|
||||
void BackTrace::print(std::ostream& out) const
|
||||
{
|
||||
out << " " << pretty_version_to_str() << std::endl;
|
||||
for (size_t i = skip; i < size; i++) {
|
||||
|
@ -35,9 +35,14 @@ struct BackTrace {
|
||||
BackTrace(const BackTrace& other);
|
||||
const BackTrace& operator=(const BackTrace& other);
|
||||
|
||||
void print(std::ostream& out);
|
||||
void print(std::ostream& out) const;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const BackTrace& bt) {
|
||||
bt.print(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -50,7 +50,6 @@ namespace ceph {
|
||||
tss << ceph_clock_now();
|
||||
|
||||
char buf[8096];
|
||||
BackTrace *bt = new BackTrace(1);
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s: In function '%s' thread %llx time %s\n"
|
||||
"%s: %d: FAILED assert(%s)\n",
|
||||
@ -60,7 +59,7 @@ namespace ceph {
|
||||
|
||||
// TODO: get rid of this memory allocation.
|
||||
ostringstream oss;
|
||||
bt->print(oss);
|
||||
oss << BackTrace(1);
|
||||
dout_emergency(oss.str());
|
||||
|
||||
dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
|
||||
@ -68,7 +67,7 @@ namespace ceph {
|
||||
|
||||
if (g_assert_context) {
|
||||
lderr(g_assert_context) << buf << std::endl;
|
||||
bt->print(*_dout);
|
||||
*_dout << oss.str();
|
||||
*_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
|
||||
<< "is needed to interpret this.\n" << dendl;
|
||||
|
||||
@ -130,7 +129,7 @@ namespace ceph {
|
||||
|
||||
// TODO: get rid of this memory allocation.
|
||||
ostringstream oss;
|
||||
bt->print(oss);
|
||||
oss << *bt;
|
||||
dout_emergency(oss.str());
|
||||
|
||||
dout_emergency(" NOTE: a copy of the executable, or `objdump -rdS <executable>` "
|
||||
@ -138,7 +137,7 @@ namespace ceph {
|
||||
|
||||
if (g_assert_context) {
|
||||
lderr(g_assert_context) << buf << std::endl;
|
||||
bt->print(*_dout);
|
||||
*_dout << oss.str();
|
||||
*_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
|
||||
<< "is needed to interpret this.\n" << dendl;
|
||||
|
||||
|
@ -329,9 +329,8 @@ handle_bad_get(CephContext *cct, string k, const char *tname)
|
||||
errstr << "bad boost::get: key " << k << " is not type " << typestr;
|
||||
lderr(cct) << errstr.str() << dendl;
|
||||
|
||||
BackTrace bt(1);
|
||||
ostringstream oss;
|
||||
bt.print(oss);
|
||||
oss << BackTrace(1);
|
||||
lderr(cct) << oss.rdbuf() << dendl;
|
||||
if (status == 0)
|
||||
free((char *)typestr);
|
||||
|
@ -129,7 +129,7 @@ int lockdep_dump_locks()
|
||||
++q) {
|
||||
lockdep_dout(0) << " * " << lock_names[q->first] << "\n";
|
||||
if (q->second)
|
||||
q->second->print(*_dout);
|
||||
*_dout << *(q->second);
|
||||
*_dout << dendl;
|
||||
}
|
||||
}
|
||||
|
@ -217,3 +217,11 @@ add_executable(unittest_dns_resolve
|
||||
target_link_libraries(unittest_dns_resolve global)
|
||||
add_ceph_unittest(unittest_dns_resolve
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_dns_resolve)
|
||||
|
||||
add_executable(unittest_back_trace
|
||||
test_back_trace.cc)
|
||||
set_source_files_properties(test_back_trace.cc PROPERTIES
|
||||
COMPILE_FLAGS -fno-inline)
|
||||
target_link_libraries(unittest_back_trace ceph-common)
|
||||
add_ceph_unittest(unittest_back_trace
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest_back_trace)
|
||||
|
41
src/test/common/test_back_trace.cc
Normal file
41
src/test/common/test_back_trace.cc
Normal file
@ -0,0 +1,41 @@
|
||||
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
||||
// vim: ts=8 sw=2 smarttab
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
// std::regex support in libstdc++ 4.8 is incomplete, so let's stick to
|
||||
// boost::regex now.
|
||||
#include <boost/regex.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "common/BackTrace.h"
|
||||
#include "common/version.h"
|
||||
|
||||
// a dummy function, so we can check "foo" in the backtrace.
|
||||
// do not mark this function as static or put it into an anonymous namespace,
|
||||
// otherwise it's function name will be removed in the backtrace.
|
||||
std::string foo()
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << ceph::BackTrace(1);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
// a typical backtrace looks like:
|
||||
//
|
||||
// ceph version Development (no_version)
|
||||
// 1: (foo[abi:cxx11]()+0x4a) [0x5562231cf22a]
|
||||
// 2: (BackTrace_Basic_Test::TestBody()+0x28) [0x5562231cf2fc]
|
||||
TEST(BackTrace, Basic) {
|
||||
std::string bt = foo();
|
||||
std::vector<std::string> lines;
|
||||
boost::split(lines, bt, boost::is_any_of("\n"));
|
||||
const unsigned lineno = 1;
|
||||
ASSERT_GT(lines.size(), lineno);
|
||||
ASSERT_EQ(lines[0].find(pretty_version_to_str()), 1);
|
||||
boost::regex e{"^ 1: "
|
||||
"\\(foo.*\\)\\s"
|
||||
"\\[0x[[:xdigit:]]+\\]$"};
|
||||
EXPECT_TRUE(boost::regex_match(lines[lineno], e));
|
||||
}
|
Loading…
Reference in New Issue
Block a user