Commit 729c33c7 by Antonio Maiorano

Improve hello_debugger

Make it so that the debugger is actually looping through all lines while in running, so that pause stops on whatever current line it's on, or setting a breakpoint will eventually hit. Also fixed breakpoint verified state for the last line, as line numbers are 1-based.
parent 9a9d46f6
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
#include "dap/protocol.h" #include "dap/protocol.h"
#include "dap/session.h" #include "dap/session.h"
#include <atomic>
#include <condition_variable> #include <condition_variable>
#include <cstdio> #include <cstdio>
#include <mutex> #include <mutex>
#include <thread>
#include <unordered_set> #include <unordered_set>
#ifdef _MSC_VER #ifdef _MSC_VER
...@@ -40,6 +42,33 @@ ...@@ -40,6 +42,33 @@
namespace { namespace {
// Event provides a basic wait and signal synchronization primitive.
class Event {
public:
// wait() blocks until the event is fired.
void wait();
// fire() sets signals the event, and unblocks any calls to wait().
void fire();
private:
std::mutex mutex;
std::condition_variable cv;
bool fired = false;
};
void Event::wait() {
std::unique_lock<std::mutex> lock(mutex);
fired = false;
cv.wait(lock, [&] { return fired; });
}
void Event::fire() {
std::unique_lock<std::mutex> lock(mutex);
fired = true;
cv.notify_all();
}
// sourceContent holds the synthetic file source. // sourceContent holds the synthetic file source.
constexpr char sourceContent[] = R"(// Hello Debugger! constexpr char sourceContent[] = R"(// Hello Debugger!
...@@ -61,9 +90,15 @@ class Debugger { ...@@ -61,9 +90,15 @@ class Debugger {
Debugger(const EventHandler&); Debugger(const EventHandler&);
// run() instructs the debugger to continue execution. // runs the debugger's main loop
void run(); void run();
// stop the debugger and terminate
void stop();
// resume() instructs the debugger to continue execution.
void resume();
// pause() instructs the debugger to pause execution. // pause() instructs the debugger to pause execution.
void pause(); void pause();
...@@ -84,24 +119,45 @@ class Debugger { ...@@ -84,24 +119,45 @@ class Debugger {
std::mutex mutex; std::mutex mutex;
int line = 1; int line = 1;
std::unordered_set<int> breakpoints; std::unordered_set<int> breakpoints;
std::atomic<bool> terminate{false};
std::atomic<bool> running{true};
::Event canRun;
}; };
Debugger::Debugger(const EventHandler& onEvent) : onEvent(onEvent) {} Debugger::Debugger(const EventHandler& onEvent) : onEvent(onEvent) {}
void Debugger::run() { void Debugger::run() {
while (!terminate) {
// If not running, wait
if (!running) {
canRun.wait();
}
// Go to next line
line = (line % numSourceLines) + 1;
// Check for breakpoints
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
for (int i = 0; i < numSourceLines; i++) { if (breakpoints.count(line)) {
auto l = ((line + i) % numSourceLines) + 1;
if (breakpoints.count(l)) {
line = l;
lock.unlock(); lock.unlock();
running = false;
onEvent(Event::BreakpointHit); onEvent(Event::BreakpointHit);
return;
} }
} }
} }
void Debugger::stop() {
terminate = true;
resume();
}
void Debugger::resume() {
running = true;
canRun.fire();
}
void Debugger::pause() { void Debugger::pause() {
running = false;
onEvent(Event::Paused); onEvent(Event::Paused);
} }
...@@ -127,32 +183,6 @@ void Debugger::addBreakpoint(int l) { ...@@ -127,32 +183,6 @@ void Debugger::addBreakpoint(int l) {
this->breakpoints.emplace(l); this->breakpoints.emplace(l);
} }
// Event provides a basic wait and signal synchronization primitive.
class Event {
public:
// wait() blocks until the event is fired.
void wait();
// fire() sets signals the event, and unblocks any calls to wait().
void fire();
private:
std::mutex mutex;
std::condition_variable cv;
bool fired = false;
};
void Event::wait() {
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [&] { return fired; });
}
void Event::fire() {
std::unique_lock<std::mutex> lock(mutex);
fired = true;
cv.notify_all();
}
} // anonymous namespace } // anonymous namespace
// main() entry point to the DAP server. // main() entry point to the DAP server.
...@@ -183,7 +213,6 @@ int main(int, char* []) { ...@@ -183,7 +213,6 @@ int main(int, char* []) {
// Signal events // Signal events
Event configured; Event configured;
Event terminate;
// Event handlers from the Debugger. // Event handlers from the Debugger.
auto onDebuggerEvent = [&](Debugger::Event onEvent) { auto onDebuggerEvent = [&](Debugger::Event onEvent) {
...@@ -225,7 +254,7 @@ int main(int, char* []) { ...@@ -225,7 +254,7 @@ int main(int, char* []) {
dap::writef(log, "dap::Session error: %s\n", msg); dap::writef(log, "dap::Session error: %s\n", msg);
log->close(); log->close();
} }
terminate.fire(); debugger.stop();
}); });
// The Initialize request is the first message sent from the client and // The Initialize request is the first message sent from the client and
...@@ -339,7 +368,7 @@ int main(int, char* []) { ...@@ -339,7 +368,7 @@ int main(int, char* []) {
// all threads. // all threads.
// https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Continue // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Continue
session->registerHandler([&](const dap::ContinueRequest&) { session->registerHandler([&](const dap::ContinueRequest&) {
debugger.run(); debugger.resume();
return dap::ContinueResponse(); return dap::ContinueResponse();
}); });
...@@ -380,7 +409,8 @@ int main(int, char* []) { ...@@ -380,7 +409,8 @@ int main(int, char* []) {
response.breakpoints.resize(breakpoints.size()); response.breakpoints.resize(breakpoints.size());
for (size_t i = 0; i < breakpoints.size(); i++) { for (size_t i = 0; i < breakpoints.size(); i++) {
debugger.addBreakpoint(breakpoints[i].line); debugger.addBreakpoint(breakpoints[i].line);
response.breakpoints[i].verified = breakpoints[i].line < numSourceLines; response.breakpoints[i].verified =
breakpoints[i].line >= 1 && breakpoints[i].line <= numSourceLines;
} }
} else { } else {
response.breakpoints.resize(breakpoints.size()); response.breakpoints.resize(breakpoints.size());
...@@ -422,7 +452,7 @@ int main(int, char* []) { ...@@ -422,7 +452,7 @@ int main(int, char* []) {
// Handler for disconnect requests // Handler for disconnect requests
session->registerHandler([&](const dap::DisconnectRequest& request) { session->registerHandler([&](const dap::DisconnectRequest& request) {
if (request.terminateDebuggee.value(false)) { if (request.terminateDebuggee.value(false)) {
terminate.fire(); debugger.stop();
} }
return dap::DisconnectResponse(); return dap::DisconnectResponse();
}); });
...@@ -461,9 +491,7 @@ int main(int, char* []) { ...@@ -461,9 +491,7 @@ int main(int, char* []) {
// This sends a stopped event to the client. // This sends a stopped event to the client.
debugger.pause(); debugger.pause();
// Block until we receive a 'terminateDebuggee' request or encounter a session debugger.run();
// error.
terminate.wait();
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment