add 'set-breakpoint', 'remove-breakpoint' commands

This commit is contained in:
MihailRis 2025-10-07 21:07:02 +03:00
parent 95f30da49b
commit 5972bc769b
6 changed files with 114 additions and 2 deletions

View File

@ -587,6 +587,7 @@ function __process_post_runnables()
__vc_named_coroutines[name] = nil
end
debug.pull_events()
network.__process_events()
block.__process_register_events()
block.__perform_ticks(time.delta())

View File

@ -1,5 +1,57 @@
-- Lua has no parallelizm, also _set_data does not call any lua functions so
-- may be reused one global ffi buffer per lua_State
local breakpoints = {}
debug.sethook(function (e, line)
local bps = breakpoints[line]
if not bps then
return
end
local source = debug.getinfo(2).source
if not bps[source] then
return
end
debug.breakpoint()
debug.pull_events()
end, "l")
local DBG_EVENT_SET_BREAKPOINT = 1
local DBG_EVENT_RM_BREAKPOINT = 2
local __pull_events = debug.__pull_events
debug.__pull_events = nil
function debug.pull_events()
local events = __pull_events()
if not events then
return
end
for i, event in ipairs(events) do
if event[1] == DBG_EVENT_SET_BREAKPOINT then
debug.set_breakpoint(event[2], event[3])
elseif event[1] == DBG_EVENT_RM_BREAKPOINT then
debug.remove_breakpoint(event[2], event[3])
end
end
end
function debug.set_breakpoint(source, line)
local bps = breakpoints[line]
if not bps then
bps = {}
breakpoints[line] = bps
end
bps[source] = true
end
function debug.remove_breakpoint(source, line)
local bps = breakpoints[line]
if not bps then
return
end
bps[source] = nil
end
local canvas_ffi_buffer
local canvas_ffi_buffer_size = 0

View File

@ -31,12 +31,14 @@ std::string ClientConnection::read() {
if (length <= 0) {
logger.error() << "invalid message length " << length;
} else {
logger.info() << "message length " << length;
messageLength = length;
}
}
} else if (connection->available() >= messageLength) {
std::string string(messageLength, 0);
connection->recv(string.data(), messageLength);
messageLength = 0;
return string;
}
return "";
@ -156,9 +158,20 @@ bool DebuggingServer::performCommand(
engine.quit();
connection->sendResponse("success");
} else if (type == "detach") {
logger.info() << "detach received";
connection->sendResponse("success");
connection.reset();
return false;
} else if (type == "set-breakpoint" || type == "remove-breakpoint") {
if (!map.has("source") || !map.has("line"))
return true;
breakpointEvents.push_back(BreakpointEvent {
type[0] == 's'
? BreakpointEventType::SET_BREAKPOINT
: BreakpointEventType::REMOVE_BREAKPOINT,
map["source"].asString(),
static_cast<int>(map["line"].asInteger()),
});
} else {
logger.error() << "unsupported command '" << type << "'";
}
@ -166,8 +179,6 @@ bool DebuggingServer::performCommand(
}
void DebuggingServer::onHitBreakpoint(dv::value&& stackTrace) {
logger.info() << "hit breakpoint:\n"
<< json::stringify(stackTrace, true, " ");
if (connection == nullptr) {
return;
}
@ -183,3 +194,7 @@ void DebuggingServer::setClient(u64id_t client) {
this->connection =
std::make_unique<ClientConnection>(engine.getNetwork(), client);
}
std::vector<BreakpointEvent> DebuggingServer::pullBreakpointEvents() {
return std::move(breakpointEvents);
}

View File

@ -2,6 +2,7 @@
#include <memory>
#include <string>
#include <vector>
#include "typedefs.hpp"
@ -35,6 +36,16 @@ namespace devtools {
u64id_t connection;
};
enum class BreakpointEventType {
SET_BREAKPOINT = 1,
REMOVE_BREAKPOINT,
};
struct BreakpointEvent {
BreakpointEventType type;
std::string source;
int line;
};
class DebuggingServer {
public:
DebuggingServer(Engine& engine, const std::string& serverString);
@ -44,10 +55,12 @@ namespace devtools {
void onHitBreakpoint(dv::value&& stackTrace);
void setClient(u64id_t client);
std::vector<BreakpointEvent> pullBreakpointEvents();
private:
Engine& engine;
network::Server& server;
std::unique_ptr<ClientConnection> connection;
std::vector<BreakpointEvent> breakpointEvents;
bool performCommand(const std::string& type, const dv::value& map);
};

View File

@ -318,6 +318,7 @@ void Engine::startPauseLoop() {
}
}
while (!isQuitSignal()) {
network->update();
if (!debuggingServer->update()) {
debuggingServer.reset();
break;

View File

@ -279,6 +279,33 @@ static int l_debug_breakpoint(lua::State* L) {
return 0;
}
static int l_debug_pull_events(lua::State* L) {
if (auto server = engine->getDebuggingServer()) {
auto events = server->pullBreakpointEvents();
if (events.empty()) {
return 0;
}
lua::createtable(L, events.size(), 0);
for (int i = 0; i < events.size(); i++) {
const auto& event = events[i];
lua::createtable(L, 3, 0);
lua::pushinteger(L, static_cast<int>(event.type));
lua::rawseti(L, 1);
lua::pushstring(L, event.source);
lua::rawseti(L, 2);
lua::pushinteger(L, event.line);
lua::rawseti(L, 3);
lua::rawseti(L, i + 1);
}
return 1;
}
return 0;
}
void initialize_libs_extends(lua::State* L) {
if (lua::getglobal(L, "debug")) {
lua::pushcfunction(L, lua::wrap<l_debug_error>);
@ -296,6 +323,9 @@ void initialize_libs_extends(lua::State* L) {
lua::pushcfunction(L, lua::wrap<l_debug_breakpoint>);
lua::setfield(L, "breakpoint");
lua::pushcfunction(L, lua::wrap<l_debug_pull_events>);
lua::setfield(L, "__pull_events");
lua::pop(L);
}
if (lua::getglobal(L, "math")) {