source: branches/stable/TEMPLATES/arb_backtrace.h

Last change on this file was 15176, checked in by westram, 8 years ago
File size: 3.6 KB
Line 
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
35class BackTraceInfo : virtual Noncopyable {
36    void   **array;
37    size_t   size;
38
39public:
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
95inline 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
Note: See TracBrowser for help on using the repository browser.