1
1
#include " backtrace.h"
2
2
3
+ #include " backtrace_lib.h"
4
+ #include " symbolizer.h"
5
+
3
6
#include < library/cpp/deprecated/atomic/atomic.h>
4
7
#include < library/cpp/malloc/api/malloc.h>
5
8
15
18
#include < util/system/mlock.h>
16
19
17
20
#ifdef _linux_
18
- #include < dlfcn.h>
19
- #include < link.h>
20
21
#include < signal.h>
21
- size_t BackTrace (void ** p, size_t len, ucontext_t * signal_ucontext);
22
22
#endif
23
23
24
24
#include < functional>
25
25
#include < vector>
26
+ #include < sstream>
27
+ #include < iostream>
26
28
27
29
#ifndef _win_
28
30
@@ -37,22 +39,21 @@ bool SetSignalHandler(int signo, void (*handler)(int)) {
37
39
38
40
namespace {
39
41
#if defined(_linux_) && defined(_x86_64_)
40
- bool SetSignalAction (int signo, void (*handler)(int , siginfo_t *, void *)) {
41
- struct sigaction sa;
42
- memset (&sa, 0 , sizeof (sa));
43
- sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
44
- sa.sa_sigaction = (decltype (sa.sa_sigaction ))handler;
45
- sigfillset (&sa.sa_mask );
46
- return sigaction (signo, &sa, nullptr ) != -1 ;
47
- }
42
+ bool SetSignalAction (int signo, void (*handler)(int , siginfo_t *, void *)) {
43
+ struct sigaction sa;
44
+ memset (&sa, 0 , sizeof (sa));
45
+ sa.sa_flags = SA_RESETHAND | SA_SIGINFO;
46
+ sa.sa_sigaction = (decltype (sa.sa_sigaction ))handler;
47
+ sigfillset (&sa.sa_mask );
48
+ return sigaction (signo, &sa, nullptr ) != -1 ;
49
+ }
48
50
#endif
49
51
} // namespace
50
52
#endif // _win_
51
53
52
54
TAtomic BacktraceStarted = 0 ;
53
55
54
- void SetFatalSignalHandler (void (*handler)(int ))
55
- {
56
+ void SetFatalSignalHandler (void (*handler)(int )) {
56
57
Y_UNUSED (handler);
57
58
#ifndef _win_
58
59
for (int signo: {SIGSEGV, SIGILL, SIGABRT, SIGFPE}) {
@@ -66,147 +67,150 @@ void SetFatalSignalHandler(void (*handler)(int))
66
67
#if defined(_linux_) && defined(_x86_64_)
67
68
void SetFatalSignalAction (void (*sigaction)(int , siginfo_t *, void *))
68
69
{
69
- Y_UNUSED (sigaction);
70
- #ifndef _win_
71
70
for (int signo: {SIGSEGV, SIGILL, SIGABRT, SIGFPE}) {
72
71
if (!SetSignalAction (signo, sigaction)) {
73
72
ythrow TSystemError () << " Cannot set sigaction for signal " << strsignal (signo);
74
73
}
75
74
}
76
- #endif
77
75
}
78
76
#endif
79
77
80
- #include < sstream>
81
- #include < iostream>
82
78
namespace {
83
- std::vector<std::function<void (int )>> Before, After;
84
- void * Stack[300 ];
85
- bool KikimrSymbolize = false ;
86
-
87
- void CallCallbacks (decltype (Before)& where, int signum) {
88
- for (const auto &fn: where) {
89
- if (fn) {
90
- fn (signum);
79
+ std::vector<std::function<void (int )>> Before, After;
80
+ bool KikimrSymbolize = false ;
81
+ const int Limit = 400 ;
82
+ NYql::NBacktrace::TCollectedFrame Frames[Limit];
83
+
84
+ void CallCallbacks (decltype (Before)& where, int signum) {
85
+ for (const auto &fn: where) {
86
+ if (fn) {
87
+ fn (signum);
88
+ }
91
89
}
92
90
}
93
- }
94
91
95
- void StackFilledCallback (IOutputStream* out, size_t stack_size) {
96
- auto symbolizer = BuildSymbolizer (KikimrSymbolize);
97
-
98
- for ( size_t i = 0 ; i < stack_size; ++i) {
99
- * out << symbolizer-> SymbolizeFrame (Stack[i] );
92
+ void PrintFrames (IOutputStream* out, const NYql::NBacktrace::TCollectedFrame* frames, size_t cnt);
93
+
94
+ void DoBacktrace (IOutputStream* out, void * data) {
95
+ auto cnt = NYql::NBacktrace::CollectFrames (Frames, data);
96
+ PrintFrames ( out, Frames, cnt );
100
97
}
101
98
102
- }
99
+ void DoBacktrace (IOutputStream* out, void ** stack, size_t cnt) {
100
+ Y_UNUSED (NYql::NBacktrace::CollectFrames (Frames, stack, cnt));
101
+ PrintFrames (out, Frames, cnt);
102
+ }
103
+
103
104
104
- void SignalHandler (int signum)
105
- {
106
- CallCallbacks (Before, signum);
105
+ void SignalHandler (int signum) {
106
+ CallCallbacks (Before, signum);
107
107
108
- if (!NMalloc::IsAllocatorCorrupted) {
109
- if (!AtomicTryLock (&BacktraceStarted)) {
110
- return ;
108
+ if (!NMalloc::IsAllocatorCorrupted) {
109
+ if (!AtomicTryLock (&BacktraceStarted)) {
110
+ return ;
111
+ }
112
+
113
+ UnlockAllMemory ();
114
+ DoBacktrace (&Cerr, nullptr );
111
115
}
112
116
113
- UnlockAllMemory ();
114
-
115
- const size_t s = BackTrace (Stack, Y_ARRAY_SIZE (Stack));
116
- StackFilledCallback (&Cerr, s);
117
+ CallCallbacks (After, signum);
118
+ raise (signum);
117
119
}
118
-
119
- CallCallbacks (After, signum);
120
-
121
- raise (signum);
122
- }
123
120
124
121
#if defined(_linux_) && defined(_x86_64_)
125
- void SignalAction (int signum, siginfo_t * sinfo, void * context)
126
- {
127
- Y_UNUSED (SignalHandler);
128
- CallCallbacks (Before, signum);
129
- Y_UNUSED (sinfo);
122
+ void SignalAction (int signum, siginfo_t *, void * context) {
123
+ Y_UNUSED (SignalHandler);
124
+ CallCallbacks (Before, signum);
130
125
131
- if (!NMalloc::IsAllocatorCorrupted) {
132
- if (!AtomicTryLock (&BacktraceStarted)) {
133
- return ;
134
- }
126
+ if (!NMalloc::IsAllocatorCorrupted) {
127
+ if (!AtomicTryLock (&BacktraceStarted)) {
128
+ return ;
129
+ }
135
130
136
- UnlockAllMemory ();
137
- const size_t s = BackTrace (Stack, Y_ARRAY_SIZE (Stack), (ucontext_t *)context);
138
- StackFilledCallback (&Cerr, s);
131
+ UnlockAllMemory ();
132
+ DoBacktrace (&Cerr, context);
133
+ }
134
+
135
+ CallCallbacks (After, signum);
136
+ raise (signum);
139
137
}
140
-
141
- CallCallbacks (After, signum);
142
-
143
- raise (signum);
144
- }
145
138
#endif
146
-
147
139
}
148
140
149
141
namespace NYql {
142
+ namespace NBacktrace {
143
+ THashMap<TString, TString> Mapping;
150
144
151
- namespace NBacktrace {
152
-
153
- THashMap<TString, TString> Mapping;
145
+ void SetModulesMapping ( const THashMap<TString, TString>& mapping) {
146
+ Mapping = mapping;
147
+ }
154
148
155
- void SetModulesMapping (const THashMap<TString, TString >& mapping ) {
156
- Mapping = mapping ;
157
- }
149
+ void AddBeforeFatalCallback (const std::function< void ( int ) >& before ) {
150
+ Before. push_back (before) ;
151
+ }
158
152
159
- void AddBeforeFatalCallback (const std::function<void (int )>& before ) {
160
- Before .push_back (before );
161
- }
153
+ void AddAfterFatalCallback (const std::function<void (int )>& after ) {
154
+ After .push_back (after );
155
+ }
162
156
163
- void AddAfterFatalCallback (const std::function<void (int )>& after) {
164
- After.push_back (after);
165
- }
157
+ void RegisterKikimrFatalActions () {
158
+ #if defined(_linux_) && defined(_x86_64_)
159
+ SetFatalSignalAction (SignalAction);
160
+ #else
161
+ SetFatalSignalHandler (SignalHandler);
162
+ #endif
163
+ }
166
164
167
- void RegisterKikimrFatalActions () {
168
- #if !defined(_linux_) || !defined(_x86_64_)
169
- SetFatalSignalHandler (SignalHandler);
170
- #else
171
- SetFatalSignalAction (SignalAction);
172
- #endif
173
- }
165
+ void EnableKikimrSymbolize () {
166
+ KikimrSymbolize = true ;
167
+ }
174
168
175
- void EnableKikimrSymbolize () {
176
- KikimrSymbolize = true ;
177
- }
169
+ void KikimrBackTrace () {
170
+ KikimrBackTraceFormatImpl (&Cerr) ;
171
+ }
178
172
179
- void KikimrBackTrace () {
180
- KikimrBackTraceFormatImpl (&Cerr);
181
- }
173
+ void KikimrBackTraceFormatImpl (IOutputStream* out) {
174
+ KikimrSymbolize = true ;
175
+ UnlockAllMemory ();
176
+ DoBacktrace (out, nullptr );
177
+ }
182
178
183
- void KikimrBackTraceFormatImpl (IOutputStream* out) {
184
- KikimrSymbolize = true ;
185
- UnlockAllMemory ();
186
- void * array[300 ];
187
- const size_t s = BackTrace (array, Y_ARRAY_SIZE (array));
188
- StackFilledCallback (out, s);
189
- }
179
+ void KikimrBacktraceFormatImpl (IOutputStream* out, void * const * stack, size_t stackSize) {
180
+ KikimrSymbolize = true ;
181
+ DoBacktrace (out, (void **)stack, stackSize);
182
+ }
190
183
191
- void KikimrBacktraceFormatImpl (IOutputStream* out, void * const * stack, size_t stackSize) {
192
- KikimrSymbolize = true ;
193
- for (size_t i = 0 ; i < stackSize; ++i) {
194
- Stack[i] = stack[i];
195
184
}
196
-
197
- StackFilledCallback (out, stackSize);
198
- }
199
-
200
- }
201
- }
202
-
203
- TString IBacktraceSymbolizer::SymbolizeFrame (void * ptr) {
204
- Y_UNUSED (ptr);
205
- return " " ;
206
- }
207
- IBacktraceSymbolizer::~IBacktraceSymbolizer () {
208
185
}
209
186
210
187
void EnableKikimrBacktraceFormat () {
211
188
SetFormatBackTraceFn (NYql::NBacktrace::KikimrBacktraceFormatImpl);
189
+ }
190
+
191
+ namespace {
192
+ void PrintFrames (IOutputStream* out, const NYql::NBacktrace::TCollectedFrame* frames, size_t count) {
193
+ auto & outp = *out;
194
+ if (KikimrSymbolize) {
195
+ TVector<NYql::NBacktrace::TStackFrame> sFrames (count);
196
+ for (size_t i = 0 ; i < count; ++i) {
197
+ sFrames [i] = NYql::NBacktrace::TStackFrame{frames[i].File , frames[i].Address };
198
+ }
199
+ auto symbolized = NYql::NBacktrace::Symbolize (sFrames );
200
+ for (auto & line: symbolized) {
201
+ outp << line << " \n " ;
202
+ }
203
+ return ;
204
+ }
205
+ outp << " StackFrames: " << count << " \n " ;
206
+ for (size_t i = 0 ; i < count; ++i) {
207
+ auto & frame = frames[i];
208
+ auto fileName = frame.File ;
209
+ if (!strcmp (fileName, " /proc/self/exe" )) {
210
+ fileName = " EXE" ;
211
+ }
212
+ auto it = NYql::NBacktrace::Mapping.find (fileName);
213
+ outp << " StackFrame: " << (it == NYql::NBacktrace::Mapping.end () ? fileName : it->second ) << " " << frame.Address << " \n " ;
214
+ }
215
+ }
212
216
}
0 commit comments