Fixed bug with GDB interrupts not being serviced properly
This commit is contained in:
@@ -18,6 +18,11 @@ namespace Bloom::DebugServer::Gdb::CommandPackets
|
|||||||
void InterruptExecution::handle(DebugSession& debugSession, TargetControllerService& targetControllerService) {
|
void InterruptExecution::handle(DebugSession& debugSession, TargetControllerService& targetControllerService) {
|
||||||
Logger::debug("Handling InterruptExecution packet");
|
Logger::debug("Handling InterruptExecution packet");
|
||||||
|
|
||||||
|
if (targetControllerService.getTargetState() == Targets::TargetState::STOPPED) {
|
||||||
|
debugSession.pendingInterrupt = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
targetControllerService.stopTargetExecution();
|
targetControllerService.stopTargetExecution();
|
||||||
debugSession.connection.writePacket(TargetStopped(Signal::INTERRUPTED));
|
debugSession.connection.writePacket(TargetStopped(Signal::INTERRUPTED));
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
*/
|
*/
|
||||||
bool waitingForBreak = false;
|
bool waitingForBreak = false;
|
||||||
|
|
||||||
|
bool pendingInterrupt = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When the user attempts to program the target via GDB's 'load' command, GDB will send a number of
|
* When the user attempts to program the target via GDB's 'load' command, GDB will send a number of
|
||||||
* FlashWrite (vFlashWrite) packets to Bloom. We group the data in these packets and flush it all at once, upon
|
* FlashWrite (vFlashWrite) packets to Bloom. We group the data in these packets and flush it all at once, upon
|
||||||
|
|||||||
@@ -127,6 +127,10 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
std::bind(&GdbRspDebugServer::onTargetExecutionStopped, this, std::placeholders::_1)
|
std::bind(&GdbRspDebugServer::onTargetExecutionStopped, this, std::placeholders::_1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this->eventListener.registerCallbackForEventType<Events::TargetExecutionResumed>(
|
||||||
|
std::bind(&GdbRspDebugServer::onTargetExecutionResumed, this, std::placeholders::_1)
|
||||||
|
);
|
||||||
|
|
||||||
if (Services::ProcessService::isManagedByClion()) {
|
if (Services::ProcessService::isManagedByClion()) {
|
||||||
Logger::warning(
|
Logger::warning(
|
||||||
"Bloom's process is being managed by CLion - Bloom will automatically shutdown upon detaching from GDB."
|
"Bloom's process is being managed by CLion - Bloom will automatically shutdown upon detaching from GDB."
|
||||||
@@ -241,6 +245,13 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
const auto rawPackets = this->activeDebugSession->connection.readRawPackets();
|
const auto rawPackets = this->activeDebugSession->connection.readRawPackets();
|
||||||
|
|
||||||
if (rawPackets.size() > 1) {
|
if (rawPackets.size() > 1) {
|
||||||
|
const auto& firstRawPacket = rawPackets.front();
|
||||||
|
|
||||||
|
if (firstRawPacket.size() == 5 && firstRawPacket[1] == 0x03) {
|
||||||
|
// Interrupt packet that came in too quickly before another packet
|
||||||
|
this->activeDebugSession->pendingInterrupt = true;
|
||||||
|
}
|
||||||
|
|
||||||
// We only process the last packet - any others will probably be duplicates from an impatient client.
|
// We only process the last packet - any others will probably be duplicates from an impatient client.
|
||||||
Logger::warning("Multiple packets received from GDB - only the most recent will be processed");
|
Logger::warning("Multiple packets received from GDB - only the most recent will be processed");
|
||||||
}
|
}
|
||||||
@@ -368,4 +379,41 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbRspDebugServer::onTargetExecutionResumed(const Events::TargetExecutionResumed&) {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
this->activeDebugSession.has_value()
|
||||||
|
&& this->activeDebugSession->pendingInterrupt
|
||||||
|
&& this->activeDebugSession->waitingForBreak
|
||||||
|
) {
|
||||||
|
Logger::info("Servicing pending interrupt");
|
||||||
|
this->targetControllerService.stopTargetExecution();
|
||||||
|
|
||||||
|
this->activeDebugSession->connection.writePacket(
|
||||||
|
ResponsePackets::TargetStopped(Signal::INTERRUPTED)
|
||||||
|
);
|
||||||
|
|
||||||
|
this->activeDebugSession->pendingInterrupt = false;
|
||||||
|
this->activeDebugSession->waitingForBreak = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (const ClientDisconnected&) {
|
||||||
|
Logger::info("GDB RSP client disconnected");
|
||||||
|
this->activeDebugSession.reset();
|
||||||
|
return;
|
||||||
|
|
||||||
|
} catch (const ClientCommunicationError& exception) {
|
||||||
|
Logger::error(
|
||||||
|
"GDB RSP client communication error - " + exception.getMessage() + " - closing connection"
|
||||||
|
);
|
||||||
|
this->activeDebugSession.reset();
|
||||||
|
return;
|
||||||
|
|
||||||
|
} catch (const DebugServerInterrupted&) {
|
||||||
|
// Server was interrupted
|
||||||
|
Logger::debug("GDB RSP interrupted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "src/EventManager/Events/TargetControllerStateChanged.hpp"
|
#include "src/EventManager/Events/TargetControllerStateChanged.hpp"
|
||||||
#include "src/EventManager/Events/TargetExecutionStopped.hpp"
|
#include "src/EventManager/Events/TargetExecutionStopped.hpp"
|
||||||
|
#include "src/EventManager/Events/TargetExecutionResumed.hpp"
|
||||||
|
|
||||||
namespace Bloom::DebugServer::Gdb
|
namespace Bloom::DebugServer::Gdb
|
||||||
{
|
{
|
||||||
@@ -197,5 +198,10 @@ namespace Bloom::DebugServer::Gdb
|
|||||||
* a "stop reply" packet to the client once the target execution stops.
|
* a "stop reply" packet to the client once the target execution stops.
|
||||||
*/
|
*/
|
||||||
void onTargetExecutionStopped(const Events::TargetExecutionStopped&);
|
void onTargetExecutionStopped(const Events::TargetExecutionStopped&);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services any pending interrupts.
|
||||||
|
*/
|
||||||
|
void onTargetExecutionResumed(const Events::TargetExecutionResumed&);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user