Skip to content

Commit 5eb211b

Browse files
committed
Implement stacktraces in Sys::Drop()/Error()
1 parent eebc034 commit 5eb211b

File tree

5 files changed

+122
-1
lines changed

5 files changed

+122
-1
lines changed

src.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ set(COMMONLIST
3535
${COMMON_DIR}/Optional.h
3636
${COMMON_DIR}/Platform.h
3737
${COMMON_DIR}/Serialize.h
38+
${COMMON_DIR}/StackTrace.h
3839
${COMMON_DIR}/String.cpp
3940
${COMMON_DIR}/String.h
4041
${COMMON_DIR}/System.cpp

src/common/StackTrace.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
===========================================================================
3+
4+
Daemon BSD Source Code
5+
Copyright (c) 2025 Daemon Developers
6+
All rights reserved.
7+
8+
This file is part of the Daemon BSD Source Code (Daemon Source Code).
9+
10+
Redistribution and use in source and binary forms, with or without
11+
modification, are permitted provided that the following conditions are met:
12+
* Redistributions of source code must retain the above copyright
13+
notice, this list of conditions and the following disclaimer.
14+
* Redistributions in binary form must reproduce the above copyright
15+
notice, this list of conditions and the following disclaimer in the
16+
documentation and/or other materials provided with the distribution.
17+
* Neither the name of the Daemon developers nor the
18+
names of its contributors may be used to endorse or promote products
19+
derived from this software without specific prior written permission.
20+
21+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24+
DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY
25+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
32+
===========================================================================
33+
*/
34+
// StackTrace.h
35+
36+
#ifndef STACKTRACE_H
37+
#define STACKTRACE_H
38+
39+
#include "CPPStandard.h"
40+
#include "String.h"
41+
42+
#include "Log.h"
43+
44+
#if defined( CPP_STACKTRACE )
45+
46+
#include <stacktrace>
47+
48+
inline std::string FormatStackTrace( const std::stacktrace& stackTrace,
49+
const bool skipCurrent = false, const bool compact = false ) {
50+
std::string out;
51+
bool skipped = !skipCurrent;
52+
bool addLineEnd = false;
53+
54+
for ( const std::stacktrace_entry& entry : stackTrace ) {
55+
if ( !skipped ) {
56+
skipped = true;
57+
continue;
58+
}
59+
60+
std::string file = entry.source_file();
61+
62+
#if defined( _MSC_VER )
63+
size_t pos = file.find( "src\\n" );
64+
#else
65+
size_t pos = file.find( "src/" );
66+
#endif
67+
68+
if ( pos != std::string::npos ) {
69+
file = file.substr( pos + 4 );
70+
}
71+
72+
if ( compact ) {
73+
#if defined( _MSC_VER )
74+
pos = file.find( "engine\\renderer-vulkan" );
75+
#else
76+
pos = file.find( "engine/renderer-vulkan" );
77+
#endif
78+
79+
if ( pos == std::string::npos ) {
80+
continue;
81+
}
82+
83+
file = file.substr( pos + 23 );
84+
}
85+
86+
if( compact ) {
87+
out += Str::Format( addLineEnd ? "\n%s:%u" : "%s:%u", file, entry.source_line() );
88+
} else {
89+
out += Str::Format( addLineEnd ? "\n%s:%u: %s" : "%s:%u: %s", file, entry.source_line(), entry.description() );
90+
}
91+
addLineEnd = true;
92+
}
93+
94+
return out;
95+
}
96+
97+
inline void PrintStackTrace( const std::stacktrace& stackTrace = std::stacktrace::current() ) {
98+
Log::Warn( "\n\n====================\nStackTrace:\n%s\n====================\n\n", FormatStackTrace( stackTrace ) );
99+
}
100+
101+
#else
102+
103+
inline void PrintStackTrace() {
104+
Log::Warn( "StackTrace unavailable: CPP23 required" );
105+
}
106+
107+
#endif
108+
109+
#endif // STACKTRACE_H

src/common/System.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5151
#include "qcommon/sys.h"
5252
#endif
5353

54+
#include "StackTrace.h"
55+
5456
namespace Sys {
5557

5658
// https://devblogs.microsoft.com/oldnewthing/20120105-00/?p=8683
@@ -224,6 +226,8 @@ void Drop(Str::StringRef message)
224226
{
225227
if (!OnMainThread()) {
226228
Sys::Error(message);
229+
} else {
230+
PrintStackTrace();
227231
}
228232

229233
// Transform into a fatal error if too many errors are generated in quick
@@ -234,8 +238,9 @@ void Drop(Str::StringRef message)
234238
if (now - lastError < std::chrono::milliseconds(100)) {
235239
if (++errorCount > 3)
236240
Sys::Error(message);
237-
} else
241+
} else {
238242
errorCount = 0;
243+
}
239244
lastError = now;
240245

241246
throw DropErr(true, message);

src/engine/framework/System.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3737
#include "System.h"
3838
#include "CrashDump.h"
3939
#include "CvarSystem.h"
40+
#include "common/StackTrace.h"
4041
#include <common/FileSystem.h>
4142
#ifdef _WIN32
4243
#include <windows.h>
@@ -556,6 +557,8 @@ void Error(Str::StringRef message)
556557
_exit(-1);
557558

558559
Log::Warn(message);
560+
PrintStackTrace();
561+
559562
Shutdown(true, message);
560563

561564
OSExit(1);

src/shared/VMMain.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3232
#include "CommonProxies.h"
3333
#include "common/IPC/CommonSyscalls.h"
3434

35+
#include "common/StackTrace.h"
36+
3537
IPC::Channel VM::rootChannel;
3638

3739
#ifdef BUILD_VM_NATIVE_EXE
@@ -121,6 +123,7 @@ void Sys::Error(Str::StringRef message)
121123
}
122124
#endif
123125

126+
PrintStackTrace();
124127
SendErrorMsg(message);
125128

126129
#ifdef BUILD_VM_IN_PROCESS

0 commit comments

Comments
 (0)