Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add thread support to debugger #64364

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ Generated\ Files/
*.pidb
*.svclog
*.scc
*.obj.enc

# Visual C++ cache files
ipch/
Expand Down
53 changes: 40 additions & 13 deletions core/debugger/debugger_marshalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,38 +32,65 @@

#include "core/io/marshalls.h"

#define CHECK_SIZE(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() < (uint32_t)(expected), false, String("Malformed ") + what + " message from script debugger, message too short. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
#define CHECK_END(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)arr.size() > (uint32_t)expected, false, String("Malformed ") + what + " message from script debugger, message too long. Expected size: " + itos(expected) + ", actual size: " + itos(arr.size()))
#define CHECK_SIZE(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)(arr).size() < (uint32_t)(expected), false, String("Malformed ") + (what) + " message from script debugger, message too short. Expected size: " + itos(expected) + ", actual size: " + itos((arr).size()))
#define CHECK_END(arr, expected, what) ERR_FAIL_COND_V_MSG((uint32_t)(arr).size() > (uint32_t)(expected), false, String("Malformed ") + (what) + " message from script debugger, message too long. Expected size: " + itos(expected) + ", actual size: " + itos((arr).size()))

Array DebuggerMarshalls::ScriptStackDump::serialize() {
Array DebuggerMarshalls::ScriptStackDump::serialize() const {
Array arr;
arr.push_back(frames.size() * 3);
for (int i = 0; i < frames.size(); i++) {
arr.push_back(frames[i].file);
arr.push_back(frames[i].line);
arr.push_back(frames[i].func);
}
if (!tid.is_zero()) {
arr.push_back(tid);
}
return arr;
}

bool DebuggerMarshalls::ScriptStackDump::deserialize(const Array &p_arr) {
CHECK_SIZE(p_arr, 1, "ScriptStackDump");
uint32_t size = p_arr[0];
const uint32_t size = p_arr[0];
CHECK_SIZE(p_arr, size, "ScriptStackDump");
int idx = 1;
for (uint32_t i = 0; i < size / 3; i++) {
ScriptLanguage::StackInfo sf;
StackInfo sf;
sf.file = p_arr[idx];
sf.line = p_arr[idx + 1];
sf.func = p_arr[idx + 2];
frames.push_back(sf);
idx += 3;
}
if (idx == p_arr.size() - 1) {
// one extra data item is optional TID
tid = p_arr[idx];
++idx;
} else {
tid.zero();
}
CHECK_END(p_arr, idx, "ScriptStackDump");
return true;
}

Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) {
void DebuggerMarshalls::ScriptStackDump::populate(const ScriptLanguageThreadContext &p_context) {
tid = p_context.debug_get_thread_id();
const int slc = p_context.debug_get_stack_level_count();
for (int i = 0; i < slc; i++) {
StackInfo frame;
frame.file = p_context.debug_get_stack_level_source(i);
frame.line = p_context.debug_get_stack_level_line(i);
frame.func = p_context.debug_get_stack_level_function(i);
frames.push_back(frame);
}
}

void DebuggerMarshalls::ScriptStackDump::clear() {
tid = DebugThreadID();
frames.clear();
}

Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) const {
Array arr;
arr.push_back(name);
arr.push_back(type);
Expand All @@ -74,7 +101,7 @@ Array DebuggerMarshalls::ScriptStackVariable::serialize(int max_size) {
}

int len = 0;
Error err = encode_variant(var, nullptr, len, true);
const Error err = encode_variant(var, nullptr, len, true);
if (err != OK) {
ERR_PRINT("Failed to encode variant.");
}
Expand All @@ -96,7 +123,7 @@ bool DebuggerMarshalls::ScriptStackVariable::deserialize(const Array &p_arr) {
return true;
}

Array DebuggerMarshalls::OutputError::serialize() {
Array DebuggerMarshalls::OutputError::serialize() const {
Array arr;
arr.push_back(hr);
arr.push_back(min);
Expand All @@ -108,8 +135,8 @@ Array DebuggerMarshalls::OutputError::serialize() {
arr.push_back(error);
arr.push_back(error_descr);
arr.push_back(warning);
unsigned int size = callstack.size();
const ScriptLanguage::StackInfo *r = callstack.ptr();
const unsigned int size = callstack.size();
const StackInfo *r = callstack.ptr();
arr.push_back(size * 3);
for (int i = 0; i < callstack.size(); i++) {
arr.push_back(r[i].file);
Expand All @@ -131,11 +158,11 @@ bool DebuggerMarshalls::OutputError::deserialize(const Array &p_arr) {
error = p_arr[7];
error_descr = p_arr[8];
warning = p_arr[9];
unsigned int stack_size = p_arr[10];
const unsigned int stack_size = p_arr[10];
CHECK_SIZE(p_arr, stack_size, "OutputError");
int idx = 11;
callstack.resize(stack_size / 3);
ScriptLanguage::StackInfo *w = callstack.ptrw();
callstack.resize(static_cast<int>(stack_size) / 3);
StackInfo *w = callstack.ptrw();
for (unsigned int i = 0; i < stack_size / 3; i++) {
w[i].file = p_arr[idx];
w[i].func = p_arr[idx + 1];
Expand Down
20 changes: 14 additions & 6 deletions core/debugger/debugger_marshalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,29 @@
#include "core/object/script_language.h"

struct DebuggerMarshalls {
using DebugThreadID = ScriptLanguageThreadContext::DebugThreadID;
using StackInfo = ScriptLanguageThreadContext::StackInfo;

struct ScriptStackVariable {
String name;
Variant value;
int type = -1;

Array serialize(int max_size = 1 << 20); // 1 MiB default.
Array serialize(int max_size = 1 << 20) const; // 1 MiB default.
bool deserialize(const Array &p_arr);
};

struct ScriptStackDump {
List<ScriptLanguage::StackInfo> frames;
ScriptStackDump() {}
DebugThreadID tid;
List<StackInfo> frames;

ScriptStackDump() = default;

Array serialize();
Array serialize() const;
bool deserialize(const Array &p_arr);

void populate(const ScriptLanguageThreadContext &p_context);
void clear();
};

struct OutputError {
Expand All @@ -62,9 +70,9 @@ struct DebuggerMarshalls {
String error;
String error_descr;
bool warning = false;
Vector<ScriptLanguage::StackInfo> callstack;
Vector<StackInfo> callstack;

Array serialize();
Array serialize() const;
bool deserialize(const Array &p_arr);
};
};
Expand Down
23 changes: 17 additions & 6 deletions core/debugger/engine_debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
#include "core/templates/hash_map.h"
#include "core/templates/vector.h"
#include "core/variant/array.h"
#include "core/variant/variant.h"

class RemoteDebuggerPeer;
class ScriptDebugger;
class ScriptLanguageThreadContext;

class EngineDebugger {
public:
Expand All @@ -61,7 +61,8 @@ class EngineDebugger {
bool active = false;

public:
Profiler() {}
Profiler() = default;

Profiler(void *p_data, ProfilingToggle p_toggle, ProfilingAdd p_add, ProfilingTick p_tick) {
data = p_data;
toggle = p_toggle;
Expand All @@ -77,7 +78,8 @@ class EngineDebugger {
void *data = nullptr;

public:
Capture() {}
Capture() = default;

Capture(void *p_data, CaptureFunc p_capture) {
data = p_data;
capture = p_capture;
Expand Down Expand Up @@ -110,7 +112,7 @@ class EngineDebugger {

static void initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints, void (*p_allow_focus_steal_fn)());
static void deinitialize();
static void register_profiler(const StringName &p_name, const Profiler &p_profiler);
static void register_profiler(const StringName &p_name, const Profiler &p_func);
static void unregister_profiler(const StringName &p_name);
static bool is_profiling(const StringName &p_name);
static bool has_profiler(const StringName &p_name);
Expand All @@ -128,10 +130,19 @@ class EngineDebugger {

void line_poll();

virtual void poll_events(bool p_is_idle) {}
virtual void poll_events(bool) {}
virtual void send_message(const String &p_msg, const Array &p_data) = 0;
virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) = 0;
virtual void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false) = 0;

// Initiate new debugging session on the caller thread and block the caller for the duration.
virtual void debug(ScriptLanguageThreadContext &p_focused_thread) = 0;

// Notify that the caller thread would like to be selected for debugging,
// but debugger is busy with another thread.
virtual void request_debug(const ScriptLanguageThreadContext &p_any_thread) = 0;

// Notify that the specified thread is held and can be inquired for stack info, but don't block.
virtual void thread_paused(const ScriptLanguageThreadContext &p_any_thread) = 0;

virtual ~EngineDebugger();
};
Expand Down
Loading