Cap the number of warnings/errors per second rather than per frame

This reproduces the behavior used for printing when using the remote
debugger. The default limit is 100 errors and 100 warnings per second,
which makes it possible to display much more GDScript warnings
before overflowing.

This also adds a "Too many warnings" message, so that warnings
don't look like errors when overflowing anymore.

This closes #21896.
This commit is contained in:
Hugo Locurcio 2019-07-31 17:24:53 +02:00
parent d66461e85a
commit 47c615caf3
No known key found for this signature in database
GPG Key ID: 39E8F8BE30B0A49C
4 changed files with 64 additions and 12 deletions

View File

@ -357,10 +357,11 @@ void ScriptDebuggerRemote::_get_output() {
locking = false;
}
if (n_errors_dropped > 0) {
if (n_errors_dropped == 1) {
// Only print one message about dropping per second
OutputError oe;
oe.error = "TOO_MANY_ERRORS";
oe.error_descr = "Too many errors! " + String::num_int64(n_errors_dropped) + " errors were dropped.";
oe.error_descr = "Too many errors! Ignoring errors for up to 1 second.";
oe.warning = false;
uint64_t time = OS::get_singleton()->get_ticks_msec();
oe.hr = time / 3600000;
@ -368,7 +369,20 @@ void ScriptDebuggerRemote::_get_output() {
oe.sec = (time / 1000) % 60;
oe.msec = time % 1000;
errors.push_back(oe);
n_errors_dropped = 0;
}
if (n_warnings_dropped == 1) {
// Only print one message about dropping per second
OutputError oe;
oe.error = "TOO_MANY_WARNINGS";
oe.error_descr = "Too many warnings! Ignoring warnings for up to 1 second.";
oe.warning = true;
uint64_t time = OS::get_singleton()->get_ticks_msec();
oe.hr = time / 3600000;
oe.min = (time / 60000) % 60;
oe.sec = (time / 1000) % 60;
oe.msec = time % 1000;
errors.push_back(oe);
}
while (errors.size()) {
@ -934,6 +948,19 @@ void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file
oe.msec = time % 1000;
Array cstack;
uint64_t ticks = OS::get_singleton()->get_ticks_usec() / 1000;
msec_count += ticks - last_msec;
last_msec = ticks;
if (msec_count > 1000) {
msec_count = 0;
err_count = 0;
n_errors_dropped = 0;
warn_count = 0;
n_warnings_dropped = 0;
}
cstack.resize(p_stack_info.size() * 3);
for (int i = 0; i < p_stack_info.size(); i++) {
cstack[i * 3 + 0] = p_stack_info[i].file;
@ -942,15 +969,28 @@ void ScriptDebuggerRemote::send_error(const String &p_func, const String &p_file
}
oe.callstack = cstack;
if (oe.warning) {
warn_count++;
} else {
err_count++;
}
mutex->lock();
if (!locking && tcp_client->is_connected_to_host()) {
if (errors.size() >= max_errors_per_frame) {
n_errors_dropped++;
if (oe.warning) {
if (warn_count > max_warnings_per_second) {
n_warnings_dropped++;
} else {
errors.push_back(oe);
}
} else {
errors.push_back(oe);
if (err_count > max_errors_per_second) {
n_errors_dropped++;
} else {
errors.push_back(oe);
}
}
}
@ -1070,10 +1110,13 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() :
mutex(Mutex::create()),
max_messages_per_frame(GLOBAL_GET("network/limits/debugger_stdout/max_messages_per_frame")),
n_messages_dropped(0),
max_errors_per_frame(GLOBAL_GET("network/limits/debugger_stdout/max_errors_per_frame")),
max_errors_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_errors_per_second")),
max_warnings_per_second(GLOBAL_GET("network/limits/debugger_stdout/max_warnings_per_second")),
n_errors_dropped(0),
max_cps(GLOBAL_GET("network/limits/debugger_stdout/max_chars_per_second")),
char_count(0),
err_count(0),
warn_count(0),
last_msec(0),
msec_count(0),
locking(false),

View File

@ -91,11 +91,15 @@ class ScriptDebuggerRemote : public ScriptDebugger {
int max_messages_per_frame;
int n_messages_dropped;
List<OutputError> errors;
int max_errors_per_frame;
int max_errors_per_second;
int max_warnings_per_second;
int n_errors_dropped;
int n_warnings_dropped;
int max_cps;
int char_count;
int err_count;
int warn_count;
uint64_t last_msec;
uint64_t msec_count;

View File

@ -650,12 +650,15 @@
<member name="network/limits/debugger_stdout/max_chars_per_second" type="int" setter="" getter="" default="2048">
Maximum amount of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
<member name="network/limits/debugger_stdout/max_errors_per_frame" type="int" setter="" getter="" default="10">
Maximum amount of errors allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
<member name="network/limits/debugger_stdout/max_errors_per_second" type="int" setter="" getter="" default="100">
Maximum number of errors allowed to be sent as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
<member name="network/limits/debugger_stdout/max_messages_per_frame" type="int" setter="" getter="" default="10">
Maximum amount of messages allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
<member name="network/limits/debugger_stdout/max_warnings_per_second" type="int" setter="" getter="" default="100">
Maximum number of warnings allowed to be sent as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection.
</member>
<member name="network/limits/packet_peer_stream/max_buffer_po2" type="int" setter="" getter="" default="16">
Default size of packet peer stream for deserializing Godot data. Over this size, data is dropped.
</member>

View File

@ -783,8 +783,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_chars_per_second", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_chars_per_second", PROPERTY_HINT_RANGE, "0, 4096, 1, or_greater"));
GLOBAL_DEF("network/limits/debugger_stdout/max_messages_per_frame", 10);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_messages_per_frame", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_messages_per_frame", PROPERTY_HINT_RANGE, "0, 20, 1, or_greater"));
GLOBAL_DEF("network/limits/debugger_stdout/max_errors_per_frame", 10);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_errors_per_frame", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_errors_per_frame", PROPERTY_HINT_RANGE, "0, 20, 1, or_greater"));
GLOBAL_DEF("network/limits/debugger_stdout/max_errors_per_second", 100);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_errors_per_second", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_errors_per_second", PROPERTY_HINT_RANGE, "0, 200, 1, or_greater"));
GLOBAL_DEF("network/limits/debugger_stdout/max_warnings_per_second", 100);
ProjectSettings::get_singleton()->set_custom_property_info("network/limits/debugger_stdout/max_warnings_per_second", PropertyInfo(Variant::INT, "network/limits/debugger_stdout/max_warnings_per_second", PROPERTY_HINT_RANGE, "0, 200, 1, or_greater"));
if (debug_mode == "remote") {