namespace ceph {
-void BackTrace::print(std::ostream& out) const
+void ClibBackTrace::print(std::ostream& out) const
{
out << " " << pretty_version_to_str() << std::endl;
for (size_t i = skip; i < size; i++) {
}
}
-void BackTrace::dump(Formatter *f) const
+void ClibBackTrace::dump(Formatter *f) const
{
f->open_array_section("backtrace");
for (size_t i = skip; i < size; i++) {
f->close_section();
}
-std::string BackTrace::demangle(const char* name)
+std::string ClibBackTrace::demangle(const char* name)
{
// find the parentheses and address offset surrounding the mangled name
#ifdef __FreeBSD__
}
}
+void PyBackTrace::dump(Formatter *f) const
+{
+ f->open_array_section("backtrace");
+ for (auto& i : strings) {
+ f->dump_string("frame", i);
+ }
+ f->close_section();
+}
+
+void PyBackTrace::print(std::ostream& out) const
+{
+ for (auto& i : strings) {
+ out << i << std::endl;
+ }
+}
+
}
class Formatter;
struct BackTrace {
+ virtual ~BackTrace() {}
+ virtual void print(std::ostream& out) const = 0;
+ virtual void dump(Formatter *f) const = 0;
+};
+
+inline std::ostream& operator<<(std::ostream& out, const BackTrace& bt) {
+ bt.print(out);
+ return out;
+}
+
+
+struct ClibBackTrace : public BackTrace {
const static int max = 32;
int skip;
size_t size;
char **strings;
- std::list<std::string> src_strings;
-
- explicit BackTrace(std::list<std::string>& s)
- : skip(0),
- size(s.size()) {
- src_strings = s;
- strings = (char **)malloc(sizeof(*strings) * src_strings.size());
- unsigned i = 0;
- for (auto& s : src_strings) {
- strings[i++] = (char *)s.c_str();
- }
- }
- explicit BackTrace(int s) : skip(s) {
+ explicit ClibBackTrace(int s) {
#ifdef HAVE_EXECINFO_H
+ skip = s;
size = backtrace(array, max);
strings = backtrace_symbols(array, size);
#else
strings = nullptr;
#endif
}
- ~BackTrace() {
+ ~ClibBackTrace() {
free(strings);
}
- BackTrace(const BackTrace& other);
- const BackTrace& operator=(const BackTrace& other);
+ ClibBackTrace(const ClibBackTrace& other);
+ const ClibBackTrace& operator=(const ClibBackTrace& other);
+
+ void print(std::ostream& out) const override;
+ void dump(Formatter *f) const override;
- void print(std::ostream& out) const;
- void dump(Formatter *f) const;
static std::string demangle(const char* name);
};
-inline std::ostream& operator<<(std::ostream& out, const BackTrace& bt) {
- bt.print(out);
- return out;
-}
+
+struct PyBackTrace : public BackTrace {
+ std::list<std::string> strings;
+
+ explicit PyBackTrace(std::list<std::string>& s) : strings(s) {}
+
+ void dump(Formatter *f) const override;
+ void print(std::ostream& out) const override;
+};
+
}
// TODO: get rid of this memory allocation.
ostringstream oss;
- oss << BackTrace(1);
+ oss << ClibBackTrace(1);
dout_emergency(oss.str());
if (g_assert_context) {
sizeof(g_assert_thread_name));
BufAppender ba(g_assert_msg, sizeof(g_assert_msg));
- BackTrace *bt = new BackTrace(1);
+ BackTrace *bt = new ClibBackTrace(1);
ba.printf("%s: In function '%s' thread %llx time %s\n"
"%s: %d: FAILED ceph_assert(%s)\n",
file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
ceph_pthread_getname(pthread_self(), g_assert_thread_name,
sizeof(g_assert_thread_name));
- BackTrace *bt = new BackTrace(1);
+ BackTrace *bt = new ClibBackTrace(1);
snprintf(g_assert_msg, sizeof(g_assert_msg),
"%s: In function '%s' thread %llx time %s\n"
"%s: %d: ceph_abort_msg(\"%s\")\n", file, func,
sizeof(g_assert_thread_name));
BufAppender ba(g_assert_msg, sizeof(g_assert_msg));
- BackTrace *bt = new BackTrace(1);
+ BackTrace *bt = new ClibBackTrace(1);
ba.printf("%s: In function '%s' thread %llx time %s\n"
"%s: %d: abort()\n",
file, func, (unsigned long long)pthread_self(), tss.str().c_str(),
lderr(cct) << errstr.str() << dendl;
ostringstream oss;
- oss << BackTrace(1);
+ oss << ClibBackTrace(1);
lderr(cct) << oss.str() << dendl;
if (status == 0)
if (!recursive) {
lockdep_dout(0) << "\n";
*_dout << "recursive lock of " << name << " (" << id << ")\n";
- auto bt = new ceph::BackTrace(BACKTRACE_SKIP);
+ auto bt = new ceph::ClibBackTrace(BACKTRACE_SKIP);
bt->print(*_dout);
if (p->second) {
*_dout << "\npreviously locked at\n";
// did we just create a cycle?
if (does_follow(id, p->first)) {
- auto bt = new ceph::BackTrace(BACKTRACE_SKIP);
+ auto bt = new ceph::ClibBackTrace(BACKTRACE_SKIP);
lockdep_dout(0) << "new dependency " << lock_names[p->first]
<< " (" << p->first << ") -> " << name << " (" << id << ")"
<< " creates a cycle at\n";
} else {
ceph::BackTrace* bt = NULL;
if (force_backtrace || lockdep_force_backtrace()) {
- bt = new ceph::BackTrace(BACKTRACE_SKIP);
+ bt = new ceph::ClibBackTrace(BACKTRACE_SKIP);
}
follows[p->first].set(id);
follows_bt[p->first][id] = bt;
lockdep_dout(20) << "_locked " << name << dendl;
if (force_backtrace || lockdep_force_backtrace())
- held[p][id] = new ceph::BackTrace(BACKTRACE_SKIP);
+ held[p][id] = new ceph::ClibBackTrace(BACKTRACE_SKIP);
else
held[p][id] = 0;
out:
// TODO: don't use an ostringstream here. It could call malloc(), which we
// don't want inside a signal handler.
// Also fix the backtrace code not to allocate memory.
- BackTrace bt(1);
+ ClibBackTrace bt(1);
ostringstream oss;
bt.print(oss);
dout_emergency(oss.str());
}
void finish(int r) override {
- BackTrace *bt = new BackTrace(1);
+ BackTrace *bt = new ClibBackTrace(1);
generic_dout(-1) << "FileStore: sync_entry timed out after "
<< m_commit_timeo << " seconds.\n";
bt->print(*_dout);
ref++;
std::lock_guard l(_ref_id_lock);
uint64_t id = ++_ref_id;
- BackTrace bt(0);
+ ClibBackTrace bt(0);
stringstream ss;
bt.print(ss);
lgeneric_subdout(cct, refs, 5) << "PG::get " << this << " " << info.pgid
std::string foo()
{
std::ostringstream oss;
- oss << ceph::BackTrace(1);
+ oss << ceph::ClibBackTrace(1);
return oss.str();
}