88#include < cstdlib>
99#include < string>
1010
11+ #if defined (__has_include)
12+ #if __has_include(<unwind.h>)
13+ #define VESPA_BACKTRACE_HAS_UNWIND_H
14+ #include < unwind.h>
15+ #endif
16+ #endif
17+
18+ namespace vespalib {
19+
1120namespace {
1221
1322/* *
@@ -44,15 +53,67 @@ demangleBacktraceLine(const std::string& line)
4453 return line;
4554}
4655
56+ #ifdef VESPA_BACKTRACE_HAS_UNWIND_H
57+
58+ struct UnwindState {
59+ // Could be done with just a current+end ptr pair, but this is more obvious
60+ void ** frames_out = nullptr ;
61+ size_t frames_written = 0 ;
62+ size_t frames_max = 0 ;
63+ };
64+
65+ _Unwind_Reason_Code unwind_callback (_Unwind_Context* ctx, void * caller_arg) {
66+ auto * my_state = static_cast <UnwindState*>(caller_arg);
67+ // We do "top of stack" frame skipping on a higher level, and therefore don't
68+ // bother with that detail here.
69+ void * frame_addr = reinterpret_cast <void *>(_Unwind_GetIP (ctx));
70+ if (frame_addr == nullptr ) {
71+ return _URC_END_OF_STACK;
72+ }
73+ my_state->frames_out [my_state->frames_written ] = frame_addr;
74+ my_state->frames_written ++;
75+ if (my_state->frames_written == my_state->frames_max ) {
76+ return _URC_END_OF_STACK;
77+ }
78+ return _URC_NO_REASON;
79+ }
80+
81+ #endif
82+
83+ } // anon ns
84+
85+ bool has_signal_safe_collect_stack_frames () noexcept {
86+ #ifdef VESPA_BACKTRACE_HAS_UNWIND_H
87+ return true ;
88+ #else
89+ return false ;
90+ #endif
91+ }
92+
93+ size_t signal_safe_collect_stack_frames (void ** frames_out, size_t frames_max) {
94+ #ifdef VESPA_BACKTRACE_HAS_UNWIND_H
95+ // The unwind callback must have room for at least 1 frame.
96+ if (frames_max == 0 ) {
97+ return 0 ;
98+ }
99+ UnwindState my_state{frames_out, 0 , frames_max};
100+ _Unwind_Backtrace (unwind_callback, &my_state);
101+ return my_state.frames_written ;
102+ #else
103+ // No known async signal safe unwinding; bail out without doing anything.
104+ (void )frames_out;
105+ (void )frames_max;
106+ return 0 ;
107+ #endif
47108}
48109
49110int
50- vespalib:: getStackTraceFrames (void ** framesOut, int maxFrames) {
111+ getStackTraceFrames (void ** framesOut, int maxFrames) {
51112 return backtrace (framesOut, maxFrames);
52113}
53114
54115std::string
55- vespalib:: getStackTrace (int ignoreTop, void * const * stack, int size)
116+ getStackTrace (int ignoreTop, void * const * stack, int size)
56117{
57118 asciistream ost;
58119 char ** symbols = backtrace_symbols (stack, size);
@@ -67,9 +128,11 @@ vespalib::getStackTrace(int ignoreTop, void* const* stack, int size)
67128}
68129
69130std::string
70- vespalib:: getStackTrace (int ignoreTop) {
131+ getStackTrace (int ignoreTop) {
71132 ignoreTop += 1 ;
72133 void * stack[25 ];
73134 int size = backtrace (stack, 25 );
74135 return getStackTrace (ignoreTop, stack, size);
75136}
137+
138+ } // vespalib
0 commit comments