From: Kefu Chai Date: Tue, 10 May 2016 13:56:55 +0000 (+0800) Subject: common/BackTrace: add operator<< X-Git-Tag: v12.0.0~163^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F9028%2Fhead;p=ceph.git common/BackTrace: add operator<< replace BackTrace::print() with the operator<< where the former is used. Signed-off-by: Kefu Chai --- diff --git a/src/common/BackTrace.cc b/src/common/BackTrace.cc index 208c5de88314..33408f33d448 100644 --- a/src/common/BackTrace.cc +++ b/src/common/BackTrace.cc @@ -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++) { diff --git a/src/common/BackTrace.h b/src/common/BackTrace.h index addfdeeeb28d..fe0ad0e7efac 100644 --- a/src/common/BackTrace.h +++ b/src/common/BackTrace.h @@ -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 diff --git a/src/common/assert.cc b/src/common/assert.cc index 340391742e8e..d4dd048c2fa1 100644 --- a/src/common/assert.cc +++ b/src/common/assert.cc @@ -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 ` " @@ -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 ` " << "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 ` " @@ -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 ` " << "is needed to interpret this.\n" << dendl; diff --git a/src/common/cmdparse.cc b/src/common/cmdparse.cc index b1e05a7c123c..3fdf94c73676 100644 --- a/src/common/cmdparse.cc +++ b/src/common/cmdparse.cc @@ -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); diff --git a/src/common/lockdep.cc b/src/common/lockdep.cc index 35d18af0ab70..b921eb64a55d 100644 --- a/src/common/lockdep.cc +++ b/src/common/lockdep.cc @@ -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; } } diff --git a/src/test/common/CMakeLists.txt b/src/test/common/CMakeLists.txt index f8ebe478089e..a08628562207 100644 --- a/src/test/common/CMakeLists.txt +++ b/src/test/common/CMakeLists.txt @@ -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) diff --git a/src/test/common/test_back_trace.cc b/src/test/common/test_back_trace.cc new file mode 100644 index 000000000000..389f4e3de3af --- /dev/null +++ b/src/test/common/test_back_trace.cc @@ -0,0 +1,41 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include +// std::regex support in libstdc++ 4.8 is incomplete, so let's stick to +// boost::regex now. +#include +#include +#include +#include + +#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 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)); +}