Skip to content

Commit 7a45095

Browse files
committed
Prevent infinite recursion during printing
1 parent 71a9948 commit 7a45095

File tree

4 files changed

+70
-14
lines changed

4 files changed

+70
-14
lines changed

core/core_bind.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,10 @@ void Logger::log_message(const String &p_text, bool p_error) {
233233
////// OS //////
234234

235235
void OS::LoggerBind::logv(const char *p_format, va_list p_list, bool p_err) {
236-
if (!should_log(p_err) || is_logging) {
236+
if (!should_log(p_err)) {
237237
return;
238238
}
239239

240-
is_logging = true;
241-
242240
constexpr int static_buf_size = 1024;
243241
char static_buf[static_buf_size] = { '\0' };
244242
char *buf = static_buf;
@@ -260,12 +258,10 @@ void OS::LoggerBind::logv(const char *p_format, va_list p_list, bool p_err) {
260258
if (len >= static_buf_size) {
261259
Memory::free_static(buf);
262260
}
263-
264-
is_logging = false;
265261
}
266262

267263
void OS::LoggerBind::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces) {
268-
if (!should_log(true) || is_logging) {
264+
if (!should_log(true)) {
269265
return;
270266
}
271267

@@ -275,13 +271,9 @@ void OS::LoggerBind::log_error(const char *p_function, const char *p_file, int p
275271
backtraces[i] = p_script_backtraces[i];
276272
}
277273

278-
is_logging = true;
279-
280274
for (Ref<CoreBind::Logger> &logger : loggers) {
281275
logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, CoreBind::Logger::ErrorType(p_type), backtraces);
282276
}
283-
284-
is_logging = false;
285277
}
286278

287279
PackedByteArray OS::get_entropy(int p_bytes) {

core/core_bind.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ class OS : public Object {
147147
mutable HashMap<String, bool> feature_cache;
148148

149149
class LoggerBind : public ::Logger {
150-
inline static thread_local bool is_logging = false;
151-
152150
public:
153151
LocalVector<Ref<CoreBind::Logger>> loggers;
154152

core/error/error_macros.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@
4343
#endif
4444

4545
static ErrorHandlerList *error_handler_list = nullptr;
46+
static thread_local bool is_printing_error = false;
47+
48+
static void _err_print_fallback(const char *p_function, const char *p_file, int p_line, const char *p_error_details, ErrorHandlerType p_type, bool p_reentrance) {
49+
if (p_reentrance) {
50+
fprintf(stderr, "Unable to print the following error, due to printing another error:\n");
51+
}
52+
53+
fprintf(stderr, "%s: %s\n", _error_handler_type_string(p_type), p_error_details);
54+
55+
if (p_function && p_file) {
56+
fprintf(stderr, " at: %s (%s:%i)\n", p_function, p_file, p_line);
57+
}
58+
}
4659

4760
void add_error_handler(ErrorHandlerList *p_handler) {
4861
// If p_handler is already in error_handler_list
@@ -91,12 +104,21 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
91104

92105
// Main error printing function.
93106
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
107+
if (is_printing_error) {
108+
// Fallback if we're already printing an error, to prevent infinite recursion.
109+
const char *err_details = (p_message && *p_message) ? p_message : p_error;
110+
_err_print_fallback(p_function, p_file, p_line, err_details, p_type, true);
111+
return;
112+
}
113+
114+
is_printing_error = true;
115+
94116
if (OS::get_singleton()) {
95117
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type, ScriptServer::capture_script_backtraces(false));
96118
} else {
97119
// Fallback if errors happen before OS init or after it's destroyed.
98120
const char *err_details = (p_message && *p_message) ? p_message : p_error;
99-
fprintf(stderr, "%s: %s\n at: %s (%s:%i)\n", _error_handler_type_string(p_type), err_details, p_function, p_file, p_line);
121+
_err_print_fallback(p_function, p_file, p_line, err_details, p_type, false);
100122
}
101123

102124
_global_lock();
@@ -108,6 +130,8 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
108130
}
109131

110132
_global_unlock();
133+
134+
is_printing_error = false;
111135
}
112136

113137
// For printing errors when we may crash at any point, so we must flush ASAP a lot of lines
@@ -116,11 +140,19 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
116140
void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type) {
117141
const char *err_details = p_error.utf8().get_data();
118142

143+
if (is_printing_error) {
144+
// Fallback if we're already printing an error, to prevent infinite recursion.
145+
_err_print_fallback(nullptr, nullptr, 0, err_details, p_type, true);
146+
return;
147+
}
148+
149+
is_printing_error = true;
150+
119151
if (OS::get_singleton()) {
120152
OS::get_singleton()->printerr("%s: %s\n", _error_handler_type_string(p_type), err_details);
121153
} else {
122154
// Fallback if errors happen before OS init or after it's destroyed.
123-
fprintf(stderr, "%s: %s\n", _error_handler_type_string(p_type), err_details);
155+
_err_print_fallback(nullptr, nullptr, 0, err_details, p_type, false);
124156
}
125157

126158
_global_lock();
@@ -132,6 +164,8 @@ void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type) {
132164
}
133165

134166
_global_unlock();
167+
168+
is_printing_error = false;
135169
}
136170

137171
// Errors with message. (All combinations of p_error and p_message as String or char*.)

core/string/print_string.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
#include "core/os/os.h"
3535

3636
static PrintHandlerList *print_handler_list = nullptr;
37+
static thread_local bool is_printing = false;
38+
39+
static void __print_fallback(const String &p_string, bool p_err) {
40+
fprintf(p_err ? stderr : stdout, "Unable to print the following message, due to printing another message:\n%s\n", p_string.utf8().get_data());
41+
}
3742

3843
void add_print_handler(PrintHandlerList *p_handler) {
3944
_global_lock();
@@ -71,6 +76,13 @@ void __print_line(const String &p_string) {
7176
return;
7277
}
7378

79+
if (is_printing) {
80+
__print_fallback(p_string, false);
81+
return;
82+
}
83+
84+
is_printing = true;
85+
7486
OS::get_singleton()->print("%s\n", p_string.utf8().get_data());
7587

7688
_global_lock();
@@ -81,6 +93,8 @@ void __print_line(const String &p_string) {
8193
}
8294

8395
_global_unlock();
96+
97+
is_printing = false;
8498
}
8599

86100
void __print_line_rich(const String &p_string) {
@@ -263,6 +277,13 @@ void __print_line_rich(const String &p_string) {
263277
}
264278
output += "\u001b[0m"; // Reset.
265279

280+
if (is_printing) {
281+
__print_fallback(output, false);
282+
return;
283+
}
284+
285+
is_printing = true;
286+
266287
OS::get_singleton()->print_rich("%s\n", output.utf8().get_data());
267288

268289
_global_lock();
@@ -273,13 +294,22 @@ void __print_line_rich(const String &p_string) {
273294
}
274295

275296
_global_unlock();
297+
298+
is_printing = false;
276299
}
277300

278301
void print_error(const String &p_string) {
279302
if (!CoreGlobals::print_error_enabled) {
280303
return;
281304
}
282305

306+
if (is_printing) {
307+
__print_fallback(p_string, true);
308+
return;
309+
}
310+
311+
is_printing = true;
312+
283313
OS::get_singleton()->printerr("%s\n", p_string.utf8().get_data());
284314

285315
_global_lock();
@@ -290,6 +320,8 @@ void print_error(const String &p_string) {
290320
}
291321

292322
_global_unlock();
323+
324+
is_printing = false;
293325
}
294326

295327
bool is_print_verbose_enabled() {

0 commit comments

Comments
 (0)