ARB
arb_backtrace.h
Go to the documentation of this file.
1 // ============================================================== //
2 // //
3 // File : arb_backtrace.h //
4 // Purpose : //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in August 2010 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // ============================================================== //
11 
12 #ifndef ARB_BACKTRACE_H
13 #define ARB_BACKTRACE_H
14 
15 #define MAX_BACKTRACE 66
16 
17 #ifndef _GLIBCXX_CSTDLIB
18 #include <cstdlib>
19 #endif
20 #ifndef _GLIBCXX_CSTDIO
21 #include <cstdio>
22 #endif
23 #ifndef _EXECINFO_H
24 #include <execinfo.h>
25 #endif
26 #ifndef ARB_ASSERT_H
27 #include <arb_assert.h>
28 #endif
29 #ifndef ARBTOOLS_H
30 #include "arbtools.h"
31 #endif
32 
33 #define ARB_CRASH_CODE(sig) (128+(sig))
34 
35 class BackTraceInfo : virtual Noncopyable {
36  void **array;
37  size_t size;
38 
39 public:
40 
41  static bool& suppress() {
42  static bool suppress_ = false;
43  return suppress_;
44  }
45 
46  explicit BackTraceInfo(size_t skipFramesAtBottom) {
47  void *tmp[MAX_BACKTRACE];
48  size = backtrace(tmp, MAX_BACKTRACE);
49 
50  if (skipFramesAtBottom>=size) skipFramesAtBottom = size-1; // show at least 1 frame
51 
52  while (1) {
53  size_t wantedFrames = size-skipFramesAtBottom;
54  arb_assert(wantedFrames>0);
55 
56  size_t msize = wantedFrames*sizeof(*array);
57  array = (void**)malloc(msize); // do NOT use ARB_alloc here
58 
59  if (array) {
60  // cppcheck-suppress arithOperationsOnVoidPointer (false positive: pointer-arithmetics on void** are completely standard compliant)
61  memcpy(array, tmp+skipFramesAtBottom, msize);
62  size = wantedFrames;
63  break;
64  }
65 
66  // reduce retrieved frames and retry
67  if (wantedFrames<=1) {
68  fputs("\n\nFATAL ERROR: not enough memory to dump backtrace!\n\n", stderr);
69  break;
70  }
71  skipFramesAtBottom += wantedFrames/2 + 1;
72  }
73  }
74  ~BackTraceInfo() { free(array); }
75 
76  bool dump(FILE *out, const char *message) const {
77  // print out all the stack frames to 'out'
78  // return true on success.
79 
80  if (fprintf(out, "\n-------------------- ARB-backtrace '%s':\n", message) < 0) return false;
81  fflush(out);
82 
83  if (array) {
84  backtrace_symbols_fd(array, size, fileno(out));
85  if (size == MAX_BACKTRACE) fputs("[stack truncated to avoid deadlock]\n", out);
86  }
87  else {
88  fputs("[could not retrieve stack-information]\n", out);
89  }
90  fputs("-------------------- End of backtrace\n", out);
91  return fflush(out) == 0;
92  }
93 };
94 
95 inline void demangle_backtrace(const class BackTraceInfo& trace, FILE *out, const char *message) {
96  if (!BackTraceInfo::suppress()) {
97  static bool filtfailed = false;
98  if (!filtfailed) {
99  // @@@ Warning: this branch ignores parameter 'out'
100  FILE *filt = popen("/usr/bin/c++filt", "w");
101  if (filt) {
102  filtfailed = !trace.dump(filt, message);
103  int exitcode = pclose(filt);
104  if (exitcode != 0 && !filtfailed) filtfailed = true;
105  }
106  else filtfailed = true;
107  }
108  if (filtfailed) trace.dump(out, message);
109  }
110 }
111 
112 
113 
114 #else
115 #error arb_backtrace.h included twice
116 #endif // ARB_BACKTRACE_H
#define arb_assert(cond)
Definition: arb_assert.h:245
static bool & suppress()
Definition: arb_backtrace.h:41
void demangle_backtrace(const class BackTraceInfo &trace, FILE *out, const char *message)
Definition: arb_backtrace.h:95
fflush(stdout)
void message(char *errortext)
fputs(TRACE_PREFIX, stderr)
BackTraceInfo(size_t skipFramesAtBottom)
Definition: arb_backtrace.h:46
#define MAX_BACKTRACE
Definition: arb_backtrace.h:15
bool dump(FILE *out, const char *message) const
Definition: arb_backtrace.h:76