blob: 559cc73550cf0957dc6e5217c7ba34551d475057 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
#include "callstack.h"
#include <util/thread/singleton.h>
#ifdef USE_ACTOR_CALLSTACK
namespace NActors {
namespace {
void (*PreviousFormatBackTrace)(IOutputStream*) = 0;
ui32 ActorBackTraceEnableCounter = 0;
}
void ActorFormatBackTrace(IOutputStream* out) {
TStringStream str;
PreviousFormatBackTrace(&str);
str << Endl;
TCallstack::DumpCallstack(str);
*out << str.Str();
}
void EnableActorCallstack() {
if (ActorBackTraceEnableCounter == 0) {
Y_ABORT_UNLESS(PreviousFormatBackTrace == 0);
PreviousFormatBackTrace = SetFormatBackTraceFn(ActorFormatBackTrace);
}
++ActorBackTraceEnableCounter;
}
void DisableActorCallstack() {
--ActorBackTraceEnableCounter;
if (ActorBackTraceEnableCounter == 0) {
Y_ABORT_UNLESS(PreviousFormatBackTrace);
SetFormatBackTraceFn(PreviousFormatBackTrace);
PreviousFormatBackTrace = 0;
}
}
TCallstack::TCallstack()
: BeginIdx(0)
, Size(0)
, LinesToSkip(0)
{
}
void TCallstack::SetLinesToSkip() {
TTrace record;
LinesToSkip = BackTrace(record.Data, TTrace::CAPACITY);
}
void TCallstack::Trace() {
size_t currentIdx = (BeginIdx + Size) % RECORDS;
if (Size == RECORDS) {
++BeginIdx;
} else {
++Size;
}
TTrace& record = Record[currentIdx];
record.Size = BackTrace(record.Data, TTrace::CAPACITY);
record.LinesToSkip = LinesToSkip;
}
void TCallstack::TraceIfEmpty() {
if (Size == 0) {
LinesToSkip = 0;
Trace();
}
}
TCallstack& TCallstack::GetTlsCallstack() {
return *FastTlsSingleton<TCallstack>();
}
void TCallstack::DumpCallstack(TStringStream& str) {
TCallstack& callstack = GetTlsCallstack();
for (int i = callstack.Size - 1; i >= 0; --i) {
TTrace& record = callstack.Record[(callstack.BeginIdx + i) % RECORDS];
str << Endl << "Trace entry " << i << Endl << Endl;
size_t size = record.Size;
if (size > record.LinesToSkip && size < TTrace::CAPACITY) {
size -= record.LinesToSkip;
}
if (size > RECORDS_TO_SKIP) {
FormatBackTrace(&str, &record.Data[RECORDS_TO_SKIP], size - RECORDS_TO_SKIP);
} else {
FormatBackTrace(&str, record.Data, size);
}
str << Endl;
}
}
}
#endif
|