tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_CrashTracer.cpp
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
15{
17 {
18 entries.ensureStorageAllocated (64);
19 }
20
21 inline void push (CrashStackTracer* c)
22 {
23 entries.add (c);
24 }
25
26 inline void pop (CrashStackTracer* c)
27 {
28 entries.removeFirstMatchingValue (c);
29 }
30
31 void dump() const
32 {
33 #if TRACKTION_LOG_ENABLED
35
36 for (int i = entries.size(); --i >= 0;)
37 threads.addIfNotAlreadyThere (entries.getUnchecked (i)->threadID);
38
39 for (int j = 0; j < threads.size(); ++j)
40 {
41 TRACKTION_LOG ("Thread " + juce::String (j) + ":");
42
43 auto thread = threads.getUnchecked(j);
44 int n = 0;
45
46 for (int i = entries.size(); --i >= 0;)
47 {
48 auto& s = *entries.getUnchecked (i);
49
50 if (s.threadID == thread)
51 {
52 if (s.pluginName != nullptr)
53 TRACKTION_LOG (" ** Plugin crashed: " + juce::String (s.pluginName));
54
55 TRACKTION_LOG (" " + juce::String (n++) + ": "
57 + ":" + juce::String (s.function) + ":" + juce::String (s.line));
58
59 }
60 }
61 }
62 #endif
63 }
64
65 void dump (juce::OutputStream& os, juce::Thread::ThreadID threadIDToDump) const
66 {
68
69 for (int i = entries.size(); --i >= 0;)
70 {
71 auto entryThreadID = entries.getUnchecked (i)->threadID;
72
73 if (entryThreadID == threadIDToDump || entryThreadID == juce::Thread::ThreadID())
74 threads.addIfNotAlreadyThere (entryThreadID);
75 }
76
77 for (int j = 0; j < threads.size(); ++j)
78 {
79 os.writeText ("Thread " + juce::String (j) + ":\n", false, false, nullptr);
80
81 auto thread = threads.getUnchecked (j);
82 int n = 0;
83
84 for (int i = entries.size(); --i >= 0;)
85 {
86 auto& s = *entries.getUnchecked (i);
87
88 if (s.threadID == thread)
89 {
90 if (s.pluginName != nullptr)
91 os.writeText (" ** Plugin crashed: " + juce::String (s.pluginName) + "\n", false, false, nullptr);
92
93 os.writeText (" " + juce::String (n++) + ": "
95 + ":" + juce::String (s.function) + ":" + juce::String (s.line) + "\n", false, false, nullptr);
96
97 }
98 }
99 }
100 }
101
102 juce::StringArray getCrashedPlugins() const
103 {
104 juce::StringArray plugins;
105
106 for (auto s : entries)
107 if (s->pluginName != nullptr)
108 plugins.add (s->pluginName);
109
110 return plugins;
111 }
112
113 juce::String getCrashedPlugin (juce::Thread::ThreadID thread)
114 {
115 for (int i = entries.size(); --i >= 0;)
116 {
117 auto& s = *entries.getUnchecked (i);
118
119 if (s.threadID == thread)
120 if (s.pluginName != nullptr)
121 return s.pluginName;
122 }
123
124 return {};
125 }
126
127 juce::String getCrashLocation (juce::Thread::ThreadID thread)
128 {
129 for (int i = entries.size(); --i >= 0;)
130 {
131 auto& s = *entries.getUnchecked (i);
132
133 if (s.threadID == thread)
135 + ":" + juce::String (s.function) + ":" + juce::String (s.line);
136 }
137
138 return "UnknownLocation";
139 }
140
142};
143
145
146CrashStackTracer::CrashStackTracer (const char* f, const char* fn, int l, const char* plugin)
147 : file (f), function (fn), pluginName (plugin), line (l), threadID (juce::Thread::getCurrentThreadId())
148{
149 crashStack.push (this);
150
151 #if ! TRACKTION_LOG_ENABLED
152 juce::ignoreUnused (file, function, pluginName, line);
153 #endif
154}
155
156CrashStackTracer::~CrashStackTracer()
157{
158 crashStack.pop (this);
159}
160
161juce::StringArray CrashStackTracer::getCrashedPlugins()
162{
163 return crashStack.getCrashedPlugins();
164}
165
166void CrashStackTracer::dump()
167{
168 TRACKTION_LOG ("Crashed");
169 TRACKTION_LOG (juce::newLine);
170 crashStack.dump();
171}
172
173void CrashStackTracer::dump (juce::OutputStream& os)
174{
175 dump (os, juce::Thread::ThreadID());
176}
177
178void CrashStackTracer::dump (juce::OutputStream& os, juce::Thread::ThreadID threadID)
179{
180 os.writeText ("Crashed", false, false, nullptr);
181 os.writeText (juce::newLine, false, false, nullptr);
182 crashStack.dump (os, threadID);
183}
184
185juce::String CrashStackTracer::getCrashedPlugin (juce::Thread::ThreadID threadID)
186{
187 return crashStack.getCrashedPlugin (threadID);
188}
189
190juce::String CrashStackTracer::getCrashLocation (juce::Thread::ThreadID threadID)
191{
192 return crashStack.getCrashLocation (threadID);
193}
194
195//==============================================================================
196DeadMansPedalMessage::DeadMansPedalMessage (PropertyStorage& ps, const juce::String& message)
197 : file (getDeadMansPedalFile (ps))
198{
199 file.replaceWithText (message);
200}
201
202DeadMansPedalMessage::~DeadMansPedalMessage()
203{
204 auto success = file.deleteFile();
205 juce::ignoreUnused (success);
206 jassert (success);
207}
208
209juce::String DeadMansPedalMessage::getAndClearLastMessage (PropertyStorage& propertyStorage)
210{
211 auto file = getDeadMansPedalFile (propertyStorage);
212 auto s = file.loadFileAsString();
213
214 if (s.isNotEmpty())
215 {
216 file.deleteFile();
217 TRACKTION_LOG (s);
218 }
219
220 return s;
221}
222
223juce::File DeadMansPedalMessage::getDeadMansPedalFile (PropertyStorage& propertyStorage)
224{
225 auto folder = propertyStorage.getAppPrefsFolder();
226 jassert (folder.exists() && folder.hasWriteAccess());
227 return folder.getChildFile ("deadMansPedal");
228}
229
230}} // namespace tracktion { inline namespace engine
ElementType getUnchecked(int index) const
int size() const noexcept
bool addIfNotAlreadyThere(ParameterType newElement)
String getFileName() const
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
virtual bool writeText(const String &text, bool asUTF16, bool writeUTF16ByteOrderMark, const char *lineEndings)
void add(String stringToAdd)
#define jassert(expression)
NewLine newLine
void ignoreUnused(Types &&...) noexcept
Used by the CRASH_TRACER macros to help provide a useful crash log of the stack.