diff options
Diffstat (limited to 'core/debugger')
-rw-r--r-- | core/debugger/debugger_marshalls.cpp | 9 | ||||
-rw-r--r-- | core/debugger/debugger_marshalls.h | 40 | ||||
-rw-r--r-- | core/debugger/engine_debugger.cpp | 75 | ||||
-rw-r--r-- | core/debugger/engine_debugger.h | 29 | ||||
-rw-r--r-- | core/debugger/local_debugger.cpp | 65 | ||||
-rw-r--r-- | core/debugger/local_debugger.h | 9 | ||||
-rw-r--r-- | core/debugger/remote_debugger.cpp | 144 | ||||
-rw-r--r-- | core/debugger/remote_debugger.h | 14 | ||||
-rw-r--r-- | core/debugger/remote_debugger_peer.cpp | 46 | ||||
-rw-r--r-- | core/debugger/remote_debugger_peer.h | 12 | ||||
-rw-r--r-- | core/debugger/script_debugger.cpp | 31 | ||||
-rw-r--r-- | core/debugger/script_debugger.h | 15 |
12 files changed, 246 insertions, 243 deletions
diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index 410c55129d..26f82c2658 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -171,7 +171,7 @@ bool DebuggerMarshalls::ServersProfilerFrame::deserialize(const Array &p_arr) { } servers.push_back(si); } - CHECK_SIZE(p_arr, idx + 3, "ServersProfilerFrame"); + CHECK_SIZE(p_arr, idx + 1, "ServersProfilerFrame"); int func_size = p_arr[idx]; idx += 1; CHECK_SIZE(p_arr, idx + func_size, "ServersProfilerFrame"); @@ -228,8 +228,9 @@ Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) { int len = 0; Error err = encode_variant(var, nullptr, len, true); - if (err != OK) + if (err != OK) { ERR_PRINT("Failed to encode variant."); + } if (len > max_size) { arr.push_back(Variant()); diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h index 04229c0afc..3e8c34d84b 100644 --- a/core/debugger/debugger_marshalls.h +++ b/core/debugger/debugger_marshalls.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,22 +31,18 @@ #ifndef DEBUGGER_MARSHARLLS_H #define DEBUGGER_MARSHARLLS_H -#include "core/script_language.h" +#include "core/object/script_language.h" #include "servers/rendering_server.h" struct DebuggerMarshalls { - // Memory usage struct ResourceInfo { String path; String format; String type; RID id; - int vram; + int vram = 0; bool operator<(const ResourceInfo &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; } - ResourceInfo() { - vram = 0; - } }; struct ResourceUsage { @@ -119,10 +115,7 @@ struct DebuggerMarshalls { struct ScriptStackVariable { String name; Variant value; - int type; - ScriptStackVariable() { - type = -1; - } + int type = -1; Array serialize(int max_size = 1 << 20); // 1 MiB default. bool deserialize(const Array &p_arr); @@ -137,34 +130,25 @@ struct DebuggerMarshalls { }; struct OutputError { - int hr; - int min; - int sec; - int msec; + int hr = -1; + int min = -1; + int sec = -1; + int msec = -1; String source_file; String source_func; - int source_line; + int source_line = -1; String error; String error_descr; - bool warning; + bool warning = false; Vector<ScriptLanguage::StackInfo> callstack; - OutputError() { - hr = -1; - min = -1; - sec = -1; - msec = -1; - source_line = -1; - warning = false; - } - Array serialize(); bool deserialize(const Array &p_arr); }; // Visual Profiler struct VisualProfilerFrame { - uint64_t frame_number; + uint64_t frame_number = 0; Vector<RS::FrameProfileArea> areas; Array serialize(); diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index bfe38d0f4a..895b8c23a9 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,7 @@ #include "core/debugger/local_debugger.h" #include "core/debugger/remote_debugger.h" +#include "core/debugger/remote_debugger_peer.h" #include "core/debugger/script_debugger.h" #include "core/os/os.h" @@ -40,6 +41,7 @@ ScriptDebugger *EngineDebugger::script_debugger = nullptr; Map<StringName, EngineDebugger::Profiler> EngineDebugger::profilers; Map<StringName, EngineDebugger::Capture> EngineDebugger::captures; +Map<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols; void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) { ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name); @@ -66,6 +68,11 @@ void EngineDebugger::unregister_message_capture(const StringName &p_name) { captures.erase(p_name); } +void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) { + ERR_FAIL_COND_MSG(protocols.has(p_protocol), "Protocol handler already registered: " + p_protocol); + protocols.insert(p_protocol, p_func); +} + void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) { ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't change profiler state, no profiler: " + p_name); Profiler &p = profilers[p_name]; @@ -104,55 +111,65 @@ Error EngineDebugger::capture_parse(const StringName &p_name, const String &p_ms void EngineDebugger::line_poll() { // The purpose of this is just processing events every now and then when the script might get too busy otherwise bugs like infinite loops can't be caught - if (poll_every % 2048 == 0) + if (poll_every % 2048 == 0) { poll_events(false); + } poll_every++; } -void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, uint64_t p_physics_ticks, float p_physics_frame_time) { +void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, float p_physics_frame_time) { frame_time = USEC_TO_SEC(p_frame_ticks); - idle_time = USEC_TO_SEC(p_idle_ticks); + process_time = USEC_TO_SEC(p_process_ticks); physics_time = USEC_TO_SEC(p_physics_ticks); physics_frame_time = p_physics_frame_time; // Notify tick to running profilers for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) { Profiler &p = E->get(); - if (!p.active || !p.tick) + if (!p.active || !p.tick) { continue; - p.tick(p.data, frame_time, idle_time, physics_time, physics_frame_time); + } + p.tick(p.data, frame_time, process_time, physics_time, physics_frame_time); } singleton->poll_events(true); } void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints) { - if (p_uri.empty()) + register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more. + if (p_uri.is_empty()) { return; + } if (p_uri == "local://") { singleton = memnew(LocalDebugger); script_debugger = memnew(ScriptDebugger); // Tell the OS that we want to handle termination signals. OS::get_singleton()->initialize_debugging(); - } else { - singleton = RemoteDebugger::create_for_uri(p_uri); - if (!singleton) + } else if (p_uri.find("://") >= 0) { + const String proto = p_uri.substr(0, p_uri.find("://") + 3); + if (!protocols.has(proto)) { return; + } + RemoteDebuggerPeer *peer = protocols[proto](p_uri); + if (!peer) { + return; + } + singleton = memnew(RemoteDebugger(Ref<RemoteDebuggerPeer>(peer))); script_debugger = memnew(ScriptDebugger); // Notify editor of our pid (to allow focus stealing). Array msg; msg.push_back(OS::get_singleton()->get_process_id()); singleton->send_message("set_pid", msg); } - if (!singleton) + if (!singleton) { return; + } // There is a debugger, parse breakpoints. ScriptDebugger *singleton_script_debugger = singleton->get_script_debugger(); singleton_script_debugger->set_skip_breakpoints(p_skip_breakpoints); for (int i = 0; i < p_breakpoints.size(); i++) { - String bp = p_breakpoints[i]; - int sp = bp.find_last(":"); + int sp = bp.rfind(":"); ERR_CONTINUE_MSG(sp == -1, "Invalid breakpoint: '" + bp + "', expected file:line format."); singleton_script_debugger->insert_breakpoint(bp.substr(sp + 1, bp.length()).to_int(), bp.substr(0, sp)); @@ -160,27 +177,31 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve } void EngineDebugger::deinitialize() { - if (!singleton) - return; - - // Stop all profilers - for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) { - if (E->get().active) - singleton->profiler_enable(E->key(), false); + if (singleton) { + // Stop all profilers + for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) { + if (E->get().active) { + singleton->profiler_enable(E->key(), false); + } + } + + // Flush any remaining message + singleton->poll_events(false); + + memdelete(singleton); + singleton = nullptr; } - // Flush any remaining message - singleton->poll_events(false); - - memdelete(singleton); - singleton = nullptr; + // Clear profilers/captuers/protocol handlers. profilers.clear(); captures.clear(); + protocols.clear(); } EngineDebugger::~EngineDebugger() { - if (script_debugger) + if (script_debugger) { memdelete(script_debugger); + } script_debugger = nullptr; singleton = nullptr; } diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 7b6b77ca9b..c6daea6e2f 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,22 +31,26 @@ #ifndef ENGINE_DEBUGGER_H #define ENGINE_DEBUGGER_H -#include "core/array.h" -#include "core/map.h" -#include "core/string_name.h" -#include "core/ustring.h" -#include "core/variant.h" -#include "core/vector.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" +#include "core/templates/map.h" +#include "core/templates/vector.h" +#include "core/variant/array.h" +#include "core/variant/variant.h" +class RemoteDebuggerPeer; class ScriptDebugger; class EngineDebugger { public: typedef void (*ProfilingToggle)(void *p_user, bool p_enable, const Array &p_opts); - typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time); + typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_process_time, float p_physics_time, float p_physics_frame_time); typedef void (*ProfilingAdd)(void *p_user, const Array &p_arr); + typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured); + typedef RemoteDebuggerPeer *(*CreatePeerFunc)(const String &p_uri); + class Profiler { friend class EngineDebugger; @@ -82,7 +86,7 @@ public: private: float frame_time = 0.0; - float idle_time = 0.0; + float process_time = 0.0; float physics_time = 0.0; float physics_frame_time = 0.0; @@ -94,6 +98,7 @@ protected: static Map<StringName, Profiler> profilers; static Map<StringName, Capture> captures; + static Map<String, CreatePeerFunc> protocols; public: _FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; } @@ -113,7 +118,9 @@ public: static void unregister_message_capture(const StringName &p_name); static bool has_capture(const StringName &p_name); - void iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, uint64_t p_physics_ticks, float p_physics_frame_time); + static void register_uri_handler(const String &p_protocol, CreatePeerFunc p_func); + + void iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, float p_physics_frame_time); void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array()); Error capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured); diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 6d88ceb2c1..1dd7e268a5 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,7 +36,6 @@ struct LocalDebugger::ScriptsProfiler { struct ProfileInfoSort { - bool operator()(const ScriptLanguage::ProfilingInfo &A, const ScriptLanguage::ProfilingInfo &B) const { return A.total_time > B.total_time; } @@ -70,17 +69,19 @@ struct LocalDebugger::ScriptsProfiler { void _print_frame_data(bool p_accumulated) { uint64_t diff = OS::get_singleton()->get_ticks_usec() - idle_accum; - if (!p_accumulated && diff < 1000000) //show every one second + if (!p_accumulated && diff < 1000000) { //show every one second return; + } idle_accum = OS::get_singleton()->get_ticks_usec(); int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { - if (p_accumulated) + if (p_accumulated) { ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&pinfo.write[ofs], pinfo.size() - ofs); - else + } else { ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&pinfo.write[ofs], pinfo.size() - ofs); + } } SortArray<ScriptLanguage::ProfilingInfo, ProfileInfoSort> sort; @@ -89,7 +90,6 @@ struct LocalDebugger::ScriptsProfiler { // compute total script frame time uint64_t script_time_us = 0; for (int i = 0; i < ofs; i++) { - script_time_us += pinfo[i].self_time; } float script_time = USEC_TO_SEC(script_time_us); @@ -102,7 +102,6 @@ struct LocalDebugger::ScriptsProfiler { } for (int i = 0; i < ofs; i++) { - print_line(itos(i) + ":" + pinfo[i].signature); float tt = USEC_TO_SEC(pinfo[i].total_time); float st = USEC_TO_SEC(pinfo[i].self_time); @@ -116,10 +115,9 @@ struct LocalDebugger::ScriptsProfiler { }; void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { - ScriptLanguage *script_lang = script_debugger->get_break_language(); - if (!target_function.empty()) { + if (!target_function.is_empty()) { String current_function = script_lang->debug_get_stack_level_function(0); if (current_function != target_function) { script_debugger->set_depth(0); @@ -135,7 +133,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { int current_frame = 0; int total_frames = script_lang->debug_get_stack_level_count(); while (true) { - OS::get_singleton()->print("debug> "); String line = OS::get_singleton()->get_stdin_string().strip_edges(); @@ -146,18 +143,15 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { print_line("\nDebugger Break, Reason: '" + script_lang->debug_get_error() + "'"); print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'"); print_line("Enter \"help\" for assistance."); - } else if (line == "c" || line == "continue") + } else if (line == "c" || line == "continue") { break; - else if (line == "bt" || line == "breakpoint") { - + } else if (line == "bt" || line == "breakpoint") { for (int i = 0; i < total_frames; i++) { - String cfi = (current_frame == i) ? "*" : " "; //current frame indicator print_line(cfi + "Frame " + itos(i) + " - " + script_lang->debug_get_stack_level_source(i) + ":" + itos(script_lang->debug_get_stack_level_line(i)) + " in function '" + script_lang->debug_get_stack_level_function(i) + "'"); } } else if (line.begins_with("fr") || line.begins_with("frame")) { - if (line.get_slice_count(" ") == 1) { print_line("*Frame " + itos(current_frame) + " - " + script_lang->debug_get_stack_level_source(current_frame) + ":" + itos(script_lang->debug_get_stack_level_line(current_frame)) + " in function '" + script_lang->debug_get_stack_level_function(current_frame) + "'"); } else { @@ -171,9 +165,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line.begins_with("set")) { - if (line.get_slice_count(" ") == 1) { - for (Map<String, String>::Element *E = options.front(); E; E = E->next()) { print_line("\t" + E->key() + "=" + E->value()); } @@ -185,13 +177,11 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { if (value_pos < 0) { print_line("Error: Invalid set format. Use: set key=value"); } else { - String key = key_value.left(value_pos); if (!options.has(key)) { print_line("Error: Unknown option " + key); } else { - // Allow explicit tab character String value = key_value.right(value_pos + 1).replace("\\t", "\t"); @@ -201,49 +191,41 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line == "lv" || line == "locals") { - List<String> locals; List<Variant> values; script_lang->debug_get_stack_level_locals(current_frame, &locals, &values); print_variables(locals, values, variable_prefix); } else if (line == "gv" || line == "globals") { - List<String> globals; List<Variant> values; script_lang->debug_get_globals(&globals, &values); print_variables(globals, values, variable_prefix); } else if (line == "mv" || line == "members") { - List<String> members; List<Variant> values; script_lang->debug_get_stack_level_members(current_frame, &members, &values); print_variables(members, values, variable_prefix); } else if (line.begins_with("p") || line.begins_with("print")) { - if (line.get_slice_count(" ") <= 1) { print_line("Usage: print <expre>"); } else { - String expr = line.get_slicec(' ', 2); String res = script_lang->debug_parse_stack_level_expression(current_frame, expr); print_line(res); } } else if (line == "s" || line == "step") { - script_debugger->set_depth(-1); script_debugger->set_lines_left(1); break; } else if (line == "n" || line == "next") { - script_debugger->set_depth(0); script_debugger->set_lines_left(1); break; } else if (line == "fin" || line == "finish") { - String current_function = script_lang->debug_get_stack_level_function(0); for (int i = 0; i < total_frames; i++) { @@ -259,9 +241,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { target_function = ""; } else if (line.begins_with("br") || line.begins_with("break")) { - if (line.get_slice_count(" ") <= 1) { - const Map<int, Set<StringName>> &breakpoints = script_debugger->get_breakpoints(); if (breakpoints.size() == 0) { print_line("No Breakpoints."); @@ -274,14 +254,14 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else { - Pair<String, int> breakpoint = to_breakpoint(line); String source = breakpoint.first; int linenr = breakpoint.second; - if (source.empty()) + if (source.is_empty()) { continue; + } script_debugger->insert_breakpoint(linenr, source); @@ -289,7 +269,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line == "q" || line == "quit") { - // Do not stop again on quit script_debugger->clear_breakpoints(); script_debugger->set_depth(-1); @@ -298,18 +277,17 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { SceneTree::get_singleton()->quit(); break; } else if (line.begins_with("delete")) { - if (line.get_slice_count(" ") <= 1) { script_debugger->clear_breakpoints(); } else { - Pair<String, int> breakpoint = to_breakpoint(line); String source = breakpoint.first; int linenr = breakpoint.second; - if (source.empty()) + if (source.is_empty()) { continue; + } script_debugger->remove_breakpoint(linenr, source); @@ -317,7 +295,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } } else if (line == "h" || line == "help") { - print_line("Built-In Debugger command list:\n"); print_line("\tc,continue\t\t Continue execution."); print_line("\tbt,backtrace\t\t Show stack trace (frames)."); @@ -340,18 +317,15 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } void LocalDebugger::print_variables(const List<String> &names, const List<Variant> &values, const String &variable_prefix) { - String value; Vector<String> value_lines; const List<Variant>::Element *V = values.front(); for (const List<String>::Element *E = names.front(); E; E = E->next()) { - value = String(V->get()); - if (variable_prefix.empty()) { + if (variable_prefix.is_empty()) { print_line(E->get() + ": " + String(V->get())); } else { - print_line(E->get() + ":"); value_lines = value.split("\n"); for (int i = 0; i < value_lines.size(); ++i) { @@ -364,7 +338,6 @@ void LocalDebugger::print_variables(const List<String> &names, const List<Varian } Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) { - String breakpoint_part = p_line.get_slicec(' ', 1); Pair<String, int> breakpoint; @@ -381,18 +354,15 @@ Pair<String, int> LocalDebugger::to_breakpoint(const String &p_line) { } void LocalDebugger::send_message(const String &p_message, const Array &p_args) { - // This needs to be cleaned up entirely. // print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args))); } void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { - - print_line("ERROR: '" + (p_descr.empty() ? p_err : p_descr) + "'"); + print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'"); } LocalDebugger::LocalDebugger() { - options["variable_prefix"] = ""; // Bind scripts profiler. @@ -411,6 +381,7 @@ LocalDebugger::LocalDebugger() { LocalDebugger::~LocalDebugger() { unregister_profiler("scripts"); - if (scripts_profiler) + if (scripts_profiler) { memdelete(scripts_profiler); + } } diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h index 2c4302f4da..e793b2a859 100644 --- a/core/debugger/local_debugger.h +++ b/core/debugger/local_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,11 +32,10 @@ #define LOCAL_DEBUGGER_H #include "core/debugger/engine_debugger.h" -#include "core/list.h" -#include "core/script_language.h" +#include "core/object/script_language.h" +#include "core/templates/list.h" class LocalDebugger : public EngineDebugger { - private: struct ScriptsProfiler; diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 97d5c71b6f..7392e6b9a6 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,13 @@ #include "remote_debugger.h" +#include "core/config/project_settings.h" #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" #include "core/input/input.h" +#include "core/object/script_language.h" #include "core/os/os.h" -#include "core/project_settings.h" -#include "core/script_language.h" #include "scene/main/node.h" #include "servers/display_server.h" @@ -57,7 +57,6 @@ void RemoteDebugger::_bind_profiler(const String &p_name, T *p_prof) { } struct RemoteDebugger::NetworkProfiler { - public: typedef DebuggerMarshalls::MultiplayerNodeInfo NodeInfo; struct BandwidthFrame { @@ -97,8 +96,9 @@ public: } void init_node(const ObjectID p_node) { - if (multiplayer_node_data.has(p_node)) + if (multiplayer_node_data.has(p_node)) { return; + } multiplayer_node_data.insert(p_node, DebuggerMarshalls::MultiplayerNodeInfo()); multiplayer_node_data[p_node].node = p_node; multiplayer_node_data[p_node].node_path = Object::cast_to<Node>(ObjectDB::get_instance(p_node))->get_path(); @@ -191,7 +191,6 @@ struct RemoteDebugger::ScriptsProfiler { typedef DebuggerMarshalls::ScriptFunctionSignature FunctionSignature; typedef DebuggerMarshalls::ScriptFunctionInfo FunctionInfo; struct ProfileInfoSort { - bool operator()(ScriptLanguage::ProfilingInfo *A, ScriptLanguage::ProfilingInfo *B) const { return A->total_time < B->total_time; } @@ -220,10 +219,11 @@ struct RemoteDebugger::ScriptsProfiler { void write_frame_data(Vector<FunctionInfo> &r_funcs, uint64_t &r_total, bool p_accumulated) { int ofs = 0; for (int i = 0; i < ScriptServer::get_language_count(); i++) { - if (p_accumulated) + if (p_accumulated) { ofs += ScriptServer::get_language(i)->profiling_get_accumulated_data(&info.write[ofs], info.size() - ofs); - else + } else { ofs += ScriptServer::get_language(i)->profiling_get_frame_data(&info.write[ofs], info.size() - ofs); + } } for (int i = 0; i < ofs; i++) { @@ -270,7 +270,6 @@ struct RemoteDebugger::ScriptsProfiler { }; struct RemoteDebugger::ServersProfiler { - bool skip_profile_frame = false; typedef DebuggerMarshalls::ServerInfo ServerInfo; typedef DebuggerMarshalls::ServerFunctionInfo ServerFunctionInfo; @@ -318,7 +317,7 @@ struct RemoteDebugger::ServersProfiler { void _send_frame_data(bool p_final) { DebuggerMarshalls::ServersProfilerFrame frame; - frame.frame_number = Engine::get_singleton()->get_idle_frames(); + frame.frame_number = Engine::get_singleton()->get_process_frames(); frame.frame_time = frame_time; frame.idle_time = idle_time; frame.physics_time = physics_time; @@ -347,7 +346,6 @@ struct RemoteDebugger::ServersProfiler { }; struct RemoteDebugger::VisualProfiler { - typedef DebuggerMarshalls::ServerInfo ServerInfo; typedef DebuggerMarshalls::ServerFunctionInfo ServerFunctionInfo; @@ -362,8 +360,9 @@ struct RemoteDebugger::VisualProfiler { void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) { Vector<RS::FrameProfileArea> profile_areas = RS::get_singleton()->get_frame_profile(); DebuggerMarshalls::VisualProfilerFrame frame; - if (!profile_areas.size()) + if (!profile_areas.size()) { return; + } frame.frame_number = RS::get_singleton()->get_frame_profile_frame(); frame.areas.append_array(profile_areas); @@ -372,26 +371,47 @@ struct RemoteDebugger::VisualProfiler { }; struct RemoteDebugger::PerformanceProfiler { - Object *performance = nullptr; int last_perf_time = 0; + uint64_t last_monitor_modification_time = 0; void toggle(bool p_enable, const Array &p_opts) {} void add(const Array &p_data) {} void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) { - if (!performance) + if (!performance) { return; + } uint64_t pt = OS::get_singleton()->get_ticks_msec(); - if (pt - last_perf_time < 1000) + if (pt - last_perf_time < 1000) { return; + } last_perf_time = pt; + + Array custom_monitor_names = performance->call("get_custom_monitor_names"); + + uint64_t monitor_modification_time = performance->call("get_monitor_modification_time"); + if (monitor_modification_time > last_monitor_modification_time) { + last_monitor_modification_time = monitor_modification_time; + EngineDebugger::get_singleton()->send_message("performance:profile_names", custom_monitor_names); + } + int max = performance->get("MONITOR_MAX"); Array arr; - arr.resize(max); + arr.resize(max + custom_monitor_names.size()); for (int i = 0; i < max; i++) { arr[i] = performance->call("get_monitor", i); } + + for (int i = 0; i < custom_monitor_names.size(); i++) { + Variant monitor_value = performance->call("get_custom_monitor", custom_monitor_names[i]); + if (!monitor_value.is_num()) { + ERR_PRINT("Value of custom monitor '" + String(custom_monitor_names[i]) + "' is not a number"); + arr[i + max] = Variant(); + } + arr[i + max] = monitor_value; + } + EngineDebugger::get_singleton()->send_message("performance:profile_frame", arr); } @@ -401,14 +421,12 @@ struct RemoteDebugger::PerformanceProfiler { }; void RemoteDebugger::_send_resource_usage() { - DebuggerMarshalls::ResourceUsage usage; List<RS::TextureInfo> tinfo; RS::get_singleton()->texture_debug_usage(&tinfo); for (List<RS::TextureInfo>::Element *E = tinfo.front(); E; E = E->next()) { - DebuggerMarshalls::ResourceInfo info; info.path = E->get().path; info.vram = E->get().bytes; @@ -430,26 +448,29 @@ Error RemoteDebugger::_put_msg(String p_message, Array p_data) { msg.push_back(p_message); msg.push_back(p_data); Error err = peer->put_message(msg); - if (err != OK) + if (err != OK) { n_messages_dropped++; + } return err; } void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) { - - if (p_type == ERR_HANDLER_SCRIPT) + if (p_type == ERR_HANDLER_SCRIPT) { return; //ignore script errors, those go through debugger + } RemoteDebugger *rd = (RemoteDebugger *)p_this; - if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) // Can't handle recursive errors during flush. + if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive errors during flush. return; + } Vector<ScriptLanguage::StackInfo> si; for (int i = 0; i < ScriptServer::get_language_count(); i++) { si = ScriptServer::get_language(i)->debug_get_current_stack_info(); - if (si.size()) + if (si.size()) { break; + } } // send_error will lock internally. @@ -457,17 +478,18 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char * } void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) { - RemoteDebugger *rd = (RemoteDebugger *)p_this; - if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) // Can't handle recursive prints during flush. + if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive prints during flush. return; + } String s = p_string; int allowed_chars = MIN(MAX(rd->max_chars_per_second - rd->char_count, 0), s.length()); - if (allowed_chars == 0 && s.length() > 0) + if (allowed_chars == 0 && s.length() > 0) { return; + } if (allowed_chars < s.length()) { s = s.substr(0, allowed_chars); @@ -478,8 +500,9 @@ void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p rd->char_count += allowed_chars; bool overflowed = rd->char_count >= rd->max_chars_per_second; if (rd->is_peer_connected()) { - if (overflowed) + if (overflowed) { s += "[...]"; + } OutputString output_string; output_string.message = s; @@ -511,17 +534,18 @@ void RemoteDebugger::flush_output() { flush_thread = Thread::get_caller_id(); flushing = true; MutexLock lock(mutex); - if (!is_peer_connected()) + if (!is_peer_connected()) { return; + } if (n_messages_dropped > 0) { ErrorMessage err_msg = _create_overflow_error("TOO_MANY_MESSAGES", "Too many messages! " + String::num_int64(n_messages_dropped) + " messages were dropped. Profiling might misbheave, try raising 'network/limits/debugger/max_queued_messages' in project setting."); - if (_put_msg("error", err_msg.serialize()) == OK) + if (_put_msg("error", err_msg.serialize()) == OK) { n_messages_dropped = 0; + } } if (output_strings.size()) { - // Join output strings so we generate less messages. Vector<String> joined_log_strings; Vector<String> strings; @@ -529,7 +553,7 @@ void RemoteDebugger::flush_output() { for (int i = 0; i < output_strings.size(); i++) { const OutputString &output_string = output_strings[i]; if (output_string.type == MESSAGE_TYPE_ERROR) { - if (!joined_log_strings.empty()) { + if (!joined_log_strings.is_empty()) { strings.push_back(String("\n").join(joined_log_strings)); types.push_back(MESSAGE_TYPE_LOG); joined_log_strings.clear(); @@ -541,7 +565,7 @@ void RemoteDebugger::flush_output() { } } - if (!joined_log_strings.empty()) { + if (!joined_log_strings.is_empty()) { strings.push_back(String("\n").join(joined_log_strings)); types.push_back(MESSAGE_TYPE_LOG); } @@ -574,7 +598,6 @@ void RemoteDebugger::flush_output() { } void RemoteDebugger::send_message(const String &p_message, const Array &p_args) { - MutexLock lock(mutex); if (is_peer_connected()) { _put_msg(p_message, p_args); @@ -582,7 +605,6 @@ void RemoteDebugger::send_message(const String &p_message, const Array &p_args) } void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { - ErrorMessage oe; oe.error = p_err; oe.error_descr = p_descr; @@ -597,8 +619,9 @@ void RemoteDebugger::send_error(const String &p_func, const String &p_file, int oe.msec = time % 1000; oe.callstack.append_array(script_debugger->get_error_stack_info()); - if (flushing && Thread::get_caller_id() == flush_thread) // Can't handle recursive errors during flush. + if (flushing && Thread::get_caller_id() == flush_thread) { // Can't handle recursive errors during flush. return; + } MutexLock lock(mutex); @@ -609,7 +632,6 @@ void RemoteDebugger::send_error(const String &p_func, const String &p_file, int } if (is_peer_connected()) { - if (oe.warning) { if (warn_count > max_warnings_per_second) { n_warnings_dropped++; @@ -657,22 +679,27 @@ Error RemoteDebugger::_try_capture(const String &p_msg, const Array &p_data, boo return OK; } const String cap = p_msg.substr(0, idx); - if (!has_capture(cap)) + if (!has_capture(cap)) { return ERR_UNAVAILABLE; // Unknown message... + } const String msg = p_msg.substr(idx + 1); return capture_parse(cap, msg, p_data, r_captured); } void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { - //this function is called when there is a debugger break (bug on script) //or when execution is paused from editor - if (script_debugger->is_skipping_breakpoints() && !p_is_error_breakpoint) + if (script_debugger->is_skipping_breakpoints() && !p_is_error_breakpoint) { return; + } ERR_FAIL_COND_MSG(!is_peer_connected(), "Script Debugger failed to connect, but being used anyway."); + if (!peer->can_block()) { + return; // Peer does not support blocking IO. We could at least send the error though. + } + ScriptLanguage *script_lang = script_debugger->get_break_language(); const String error_str = script_lang ? script_lang->debug_get_error() : ""; Array msg; @@ -683,8 +710,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { servers_profiler->skip_profile_frame = true; // Avoid frame time spike in debug. Input::MouseMode mouse_mode = Input::get_singleton()->get_mouse_mode(); - if (mouse_mode != Input::MOUSE_MODE_VISIBLE) + if (mouse_mode != Input::MOUSE_MODE_VISIBLE) { Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + } uint64_t loop_begin_usec = 0; uint64_t loop_time_sec = 0; @@ -695,7 +723,6 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { peer->poll(); if (peer->has_message()) { - Array cmd = peer->get_message(); ERR_CONTINUE(cmd.size() != 2); @@ -773,10 +800,11 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else if (command == "breakpoint") { ERR_FAIL_COND(data.size() < 3); bool set = data[2]; - if (set) + if (set) { script_debugger->insert_breakpoint(data[1], data[0]); - else + } else { script_debugger->remove_breakpoint(data[1], data[0]); + } } else if (command == "set_skip_breakpoints") { ERR_FAIL_COND(data.size() < 1); @@ -784,8 +812,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { } else { bool captured = false; ERR_CONTINUE(_try_capture(command, data, captured) != OK); - if (!captured) + if (!captured) { WARN_PRINT("Unknown message received from debugger: " + command); + } } } else { OS::get_singleton()->delay_usec(10000); @@ -802,18 +831,19 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { send_message("debug_exit", Array()); - if (mouse_mode != Input::MOUSE_MODE_VISIBLE) + if (mouse_mode != Input::MOUSE_MODE_VISIBLE) { Input::get_singleton()->set_mouse_mode(mouse_mode); + } } void RemoteDebugger::poll_events(bool p_is_idle) { - if (peer.is_null()) + if (peer.is_null()) { return; + } flush_output(); peer->poll(); while (peer->has_message()) { - Array arr = peer->get_message(); ERR_CONTINUE(arr.size() != 2); @@ -829,8 +859,9 @@ void RemoteDebugger::poll_events(bool p_is_idle) { } const String cap = cmd.substr(0, idx); - if (!has_capture(cap)) + if (!has_capture(cap)) { continue; // Unknown message... + } const String msg = cmd.substr(idx + 1); capture_parse(cap, msg, arr[1], parsed); @@ -853,10 +884,11 @@ Error RemoteDebugger::_core_capture(const String &p_cmd, const Array &p_data, bo } else if (p_cmd == "breakpoint") { ERR_FAIL_COND_V(p_data.size() < 3, ERR_INVALID_DATA); bool set = p_data[2]; - if (set) + if (set) { script_debugger->insert_breakpoint(p_data[1], p_data[0]); - else + } else { script_debugger->remove_breakpoint(p_data[1], p_data[0]); + } } else if (p_cmd == "set_skip_breakpoints") { ERR_FAIL_COND_V(p_data.size() < 1, ERR_INVALID_DATA); @@ -886,13 +918,6 @@ Error RemoteDebugger::_profiler_capture(const String &p_cmd, const Array &p_data return OK; } -RemoteDebugger *RemoteDebugger::create_for_uri(const String &p_uri) { - Ref<RemoteDebuggerPeer> peer = RemoteDebuggerPeer::create_from_uri(p_uri); - if (peer.is_valid()) - return memnew(RemoteDebugger(peer)); - return nullptr; -} - RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) { peer = p_peer; max_chars_per_second = GLOBAL_GET("network/limits/debugger/max_chars_per_second"); @@ -954,6 +979,7 @@ RemoteDebugger::~RemoteDebugger() { memdelete(servers_profiler); memdelete(network_profiler); memdelete(visual_profiler); - if (performance_profiler) + if (performance_profiler) { memdelete(performance_profiler); + } } diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index cac0bc3730..28e670747e 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,13 @@ #ifndef REMOTE_DEBUGGER_H #define REMOTE_DEBUGGER_H -#include "core/array.h" #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/remote_debugger_peer.h" -#include "core/object.h" -#include "core/string_name.h" -#include "core/ustring.h" +#include "core/object/class_db.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" +#include "core/variant/array.h" class RemoteDebugger : public EngineDebugger { public: @@ -108,8 +108,6 @@ private: Error _try_capture(const String &p_name, const Array &p_data, bool &r_captured); public: - static RemoteDebugger *create_for_uri(const String &p_uri); - // Overrides void poll_events(bool p_is_idle); void send_message(const String &p_message, const Array &p_args); diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index ed04431177..2e388d5934 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "remote_debugger_peer.h" +#include "core/config/project_settings.h" #include "core/io/marshalls.h" #include "core/os/os.h" -#include "core/project_settings.h" bool RemoteDebuggerPeerTCP::is_peer_connected() { return connected; @@ -52,8 +52,9 @@ Array RemoteDebuggerPeerTCP::get_message() { Error RemoteDebuggerPeerTCP::put_message(const Array &p_arr) { MutexLock lock(mutex); - if (out_queue.size() >= max_queued_messages) + if (out_queue.size() >= max_queued_messages) { return ERR_OUT_OF_MEMORY; + } out_queue.push_back(p_arr); return OK; @@ -99,8 +100,9 @@ void RemoteDebuggerPeerTCP::_write_out() { while (tcp_client->poll(NetSocket::POLL_TYPE_OUT) == OK) { uint8_t *buf = out_buf.ptrw(); if (out_left <= 0) { - if (out_queue.size() == 0) + if (out_queue.size() == 0) { break; // Nothing left to send + } mutex.lock(); Variant var = out_queue[0]; out_queue.pop_front(); @@ -154,12 +156,12 @@ void RemoteDebuggerPeerTCP::_read_in() { } Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) { - IP_Address ip; - if (p_host.is_valid_ip_address()) + if (p_host.is_valid_ip_address()) { ip = p_host; - else + } else { ip = IP::get_singleton()->resolve_hostname(p_host); + } int port = p_port; @@ -169,23 +171,20 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po tcp_client->connect_to_host(ip, port); for (int i = 0; i < tries; i++) { - if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) { print_verbose("Remote Debugger: Connected!"); break; } else { - const int ms = waits[i]; OS::get_singleton()->delay_usec(ms * 1000); print_verbose("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec."); - }; - }; + } + } if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) { - ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(tcp_client->get_status()) + "."); return FAILED; - }; + } connected = true; #ifndef NO_THREADS running = true; @@ -198,8 +197,9 @@ void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) { RemoteDebuggerPeerTCP *peer = (RemoteDebuggerPeerTCP *)p_ud; while (peer->running && peer->is_peer_connected()) { peer->_poll(); - if (!peer->is_peer_connected()) + if (!peer->is_peer_connected()) { break; + } peer->tcp_client->poll(NetSocket::POLL_TYPE_IN_OUT, 1); } } @@ -218,22 +218,24 @@ void RemoteDebuggerPeerTCP::_poll() { } } -Ref<RemoteDebuggerPeer> RemoteDebuggerPeer::create_from_uri(const String p_uri) { - if (!p_uri.begins_with("tcp://")) - return Ref<RemoteDebuggerPeer>(); // Only TCP supported for now, more to come. +RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) { + ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr); String debug_host = p_uri.replace("tcp://", ""); uint16_t debug_port = 6007; if (debug_host.find(":") != -1) { - int sep_pos = debug_host.find_last(":"); + int sep_pos = debug_host.rfind(":"); debug_port = debug_host.substr(sep_pos + 1).to_int(); debug_host = debug_host.substr(0, sep_pos); } - Ref<RemoteDebuggerPeerTCP> peer = Ref<RemoteDebuggerPeer>(memnew(RemoteDebuggerPeerTCP)); + + RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP); Error err = peer->connect_to_host(debug_host, debug_port); - if (err != OK) - return Ref<RemoteDebuggerPeer>(); + if (err != OK) { + memdelete(peer); + return nullptr; + } return peer; } diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h index e4b838f145..c759c65568 100644 --- a/core/debugger/remote_debugger_peer.h +++ b/core/debugger/remote_debugger_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,17 +32,16 @@ #define REMOTE_DEBUGGER_PEER_H #include "core/io/stream_peer_tcp.h" +#include "core/object/reference.h" #include "core/os/mutex.h" #include "core/os/thread.h" -#include "core/reference.h" -#include "core/ustring.h" +#include "core/string/ustring.h" class RemoteDebuggerPeer : public Reference { protected: int max_queued_messages = 4096; public: - static Ref<RemoteDebuggerPeer> create_from_uri(const String p_uri); virtual bool is_peer_connected() = 0; virtual bool has_message() = 0; virtual Error put_message(const Array &p_arr) = 0; @@ -50,6 +49,7 @@ public: virtual void close() = 0; virtual void poll() = 0; virtual int get_max_message_size() const = 0; + virtual bool can_block() const { return true; } // If blocking io is allowed on main thread (debug). RemoteDebuggerPeer(); }; @@ -77,6 +77,8 @@ private: void _read_in(); public: + static RemoteDebuggerPeer *create(const String &p_uri); + Error connect_to_host(const String &p_host, uint16_t p_port); void poll(); diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index 935ad01d80..6d1e4ed101 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,69 +33,63 @@ #include "core/debugger/engine_debugger.h" void ScriptDebugger::set_lines_left(int p_left) { - lines_left = p_left; } int ScriptDebugger::get_lines_left() const { - return lines_left; } void ScriptDebugger::set_depth(int p_depth) { - depth = p_depth; } int ScriptDebugger::get_depth() const { - return depth; } void ScriptDebugger::insert_breakpoint(int p_line, const StringName &p_source) { - - if (!breakpoints.has(p_line)) + if (!breakpoints.has(p_line)) { breakpoints[p_line] = Set<StringName>(); + } breakpoints[p_line].insert(p_source); } void ScriptDebugger::remove_breakpoint(int p_line, const StringName &p_source) { - - if (!breakpoints.has(p_line)) + if (!breakpoints.has(p_line)) { return; + } breakpoints[p_line].erase(p_source); - if (breakpoints[p_line].size() == 0) + if (breakpoints[p_line].size() == 0) { breakpoints.erase(p_line); + } } -bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const { - if (!breakpoints.has(p_line)) +bool ScriptDebugger::is_breakpoint(int p_line, const StringName &p_source) const { + if (!breakpoints.has(p_line)) { return false; + } return breakpoints[p_line].has(p_source); } -bool ScriptDebugger::is_breakpoint_line(int p_line) const { +bool ScriptDebugger::is_breakpoint_line(int p_line) const { return breakpoints.has(p_line); } String ScriptDebugger::breakpoint_find_source(const String &p_source) const { - return p_source; } void ScriptDebugger::clear_breakpoints() { - breakpoints.clear(); } void ScriptDebugger::set_skip_breakpoints(bool p_skip_breakpoints) { - skip_breakpoints = p_skip_breakpoints; } bool ScriptDebugger::is_skipping_breakpoints() { - return skip_breakpoints; } @@ -118,6 +112,5 @@ Vector<ScriptLanguage::StackInfo> ScriptDebugger::get_error_stack_info() const { } ScriptLanguage *ScriptDebugger::get_break_language() const { - return break_lang; } diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index e5066273d2..9f034a5e5d 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,14 +31,13 @@ #ifndef SCRIPT_DEBUGGER_H #define SCRIPT_DEBUGGER_H -#include "core/map.h" -#include "core/script_language.h" -#include "core/set.h" -#include "core/string_name.h" -#include "core/vector.h" +#include "core/object/script_language.h" +#include "core/string/string_name.h" +#include "core/templates/map.h" +#include "core/templates/set.h" +#include "core/templates/vector.h" class ScriptDebugger { - typedef ScriptLanguage::StackInfo StackInfo; int lines_left = -1; |