mirror of https://github.com/mgba-emu/mgba.git
Debugger: Add debugger polling to avoid blocking
This commit is contained in:
parent
a00f2939ad
commit
257122796c
|
@ -152,7 +152,7 @@ struct mDebuggerModule {
|
|||
void (*init)(struct mDebuggerModule*);
|
||||
void (*deinit)(struct mDebuggerModule*);
|
||||
|
||||
void (*paused)(struct mDebuggerModule*);
|
||||
void (*paused)(struct mDebuggerModule*, int32_t timeoutMs);
|
||||
void (*update)(struct mDebuggerModule*);
|
||||
void (*entered)(struct mDebuggerModule*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
void (*custom)(struct mDebuggerModule*);
|
||||
|
@ -166,6 +166,7 @@ void mDebuggerDeinit(struct mDebugger*);
|
|||
void mDebuggerAttach(struct mDebugger*, struct mCore*);
|
||||
void mDebuggerAttachModule(struct mDebugger*, struct mDebuggerModule*);
|
||||
void mDebuggerDetachModule(struct mDebugger*, struct mDebuggerModule*);
|
||||
void mDebuggerRunTimeout(struct mDebugger* debugger, int32_t timeoutMs);
|
||||
void mDebuggerRun(struct mDebugger*);
|
||||
void mDebuggerRunFrame(struct mDebugger*);
|
||||
void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
|
||||
|
|
|
@ -73,6 +73,7 @@ struct CLIDebuggerBackend {
|
|||
|
||||
ATTRIBUTE_FORMAT(printf, 2, 3)
|
||||
void (*printf)(struct CLIDebuggerBackend*, const char* fmt, ...);
|
||||
int (*poll)(struct CLIDebuggerBackend*, int32_t timeoutMs);
|
||||
const char* (*readline)(struct CLIDebuggerBackend*, size_t* len);
|
||||
void (*lineAppend)(struct CLIDebuggerBackend*, const char* line);
|
||||
const char* (*historyLast)(struct CLIDebuggerBackend*, size_t* len);
|
||||
|
|
|
@ -41,7 +41,6 @@ struct GDBStub {
|
|||
Socket socket;
|
||||
Socket connection;
|
||||
|
||||
bool shouldBlock;
|
||||
int untilPoll;
|
||||
|
||||
bool supportsSwbreak;
|
||||
|
@ -56,7 +55,7 @@ bool GDBStubListen(struct GDBStub*, int port, const struct Address* bindAddress,
|
|||
void GDBStubHangup(struct GDBStub*);
|
||||
void GDBStubShutdown(struct GDBStub*);
|
||||
|
||||
void GDBStubUpdate(struct GDBStub*);
|
||||
bool GDBStubUpdate(struct GDBStub*, int timeoutMs);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
|
|
|
@ -1092,7 +1092,7 @@ bool CLIDebuggerRunCommand(struct CLIDebugger* debugger, const char* line, size_
|
|||
return false;
|
||||
}
|
||||
|
||||
static void _commandLine(struct mDebuggerModule* debugger) {
|
||||
static void _commandLine(struct mDebuggerModule* debugger, int32_t timeoutMs) {
|
||||
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
|
||||
const char* line;
|
||||
size_t len;
|
||||
|
@ -1102,15 +1102,20 @@ static void _commandLine(struct mDebuggerModule* debugger) {
|
|||
_printStatus(cliDebugger, 0);
|
||||
}
|
||||
while (debugger->isPaused && !mDebuggerIsShutdown(debugger->p)) {
|
||||
int poll = cliDebugger->backend->poll(cliDebugger->backend, timeoutMs);
|
||||
if (poll <= 0) {
|
||||
if (poll < 0) {
|
||||
mDebuggerShutdown(debugger->p);
|
||||
} else {
|
||||
cliDebugger->skipStatus = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
line = cliDebugger->backend->readline(cliDebugger->backend, &len);
|
||||
if (!line || len == 0) {
|
||||
mDebuggerShutdown(debugger->p);
|
||||
return;
|
||||
}
|
||||
if (line[0] == '\033') {
|
||||
cliDebugger->skipStatus = true;
|
||||
return;
|
||||
}
|
||||
if (line[0] == '\n') {
|
||||
line = cliDebugger->backend->historyLast(cliDebugger->backend, &len);
|
||||
if (line && len) {
|
||||
|
|
|
@ -118,7 +118,7 @@ void mDebuggerDetachModule(struct mDebugger* debugger, struct mDebuggerModule* m
|
|||
}
|
||||
}
|
||||
|
||||
void mDebuggerRun(struct mDebugger* debugger) {
|
||||
void mDebuggerRunTimeout(struct mDebugger* debugger, int32_t timeoutMs) {
|
||||
size_t i;
|
||||
size_t anyPaused = 0;
|
||||
|
||||
|
@ -146,7 +146,7 @@ void mDebuggerRun(struct mDebugger* debugger) {
|
|||
struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i);
|
||||
if (module->isPaused) {
|
||||
if (module->paused) {
|
||||
module->paused(module);
|
||||
module->paused(module, timeoutMs);
|
||||
}
|
||||
if (module->isPaused) {
|
||||
++anyPaused;
|
||||
|
@ -167,6 +167,10 @@ void mDebuggerRun(struct mDebugger* debugger) {
|
|||
}
|
||||
}
|
||||
|
||||
void mDebuggerRun(struct mDebugger* debugger) {
|
||||
mDebuggerRunTimeout(debugger, 50);
|
||||
}
|
||||
|
||||
void mDebuggerRunFrame(struct mDebugger* debugger) {
|
||||
uint32_t frame = debugger->core->frameCounter(debugger->core);
|
||||
do {
|
||||
|
@ -309,7 +313,5 @@ bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int
|
|||
|
||||
void mDebuggerModuleSetNeedsCallback(struct mDebuggerModule* debugger) {
|
||||
debugger->needsCallback = true;
|
||||
if (debugger->p->state == DEBUGGER_RUNNING) {
|
||||
debugger->p->state = DEBUGGER_CALLBACK;
|
||||
}
|
||||
mDebuggerUpdatePaused(debugger->p);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#define SIGTRAP 5 /* Win32 Signals do not include SIGTRAP */
|
||||
#endif
|
||||
|
||||
#define SOCKET_TIMEOUT 50
|
||||
|
||||
enum GDBError {
|
||||
GDB_NO_ERROR = 0x00,
|
||||
GDB_BAD_ARGUMENTS = 0x06,
|
||||
|
@ -135,20 +133,17 @@ static void _gdbStubPoll(struct mDebuggerModule* debugger) {
|
|||
return;
|
||||
}
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
stub->shouldBlock = false;
|
||||
GDBStubUpdate(stub);
|
||||
GDBStubUpdate(stub, 0);
|
||||
}
|
||||
|
||||
static void _gdbStubWait(struct mDebuggerModule* debugger) {
|
||||
static void _gdbStubWait(struct mDebuggerModule* debugger, int32_t timeoutMs) {
|
||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||
stub->shouldBlock = true;
|
||||
GDBStubUpdate(stub);
|
||||
GDBStubUpdate(stub, timeoutMs);
|
||||
}
|
||||
|
||||
static void _gdbStubUpdate(struct mDebuggerModule* debugger) {
|
||||
struct GDBStub* stub = (struct GDBStub*) debugger;
|
||||
stub->shouldBlock = false;
|
||||
GDBStubUpdate(stub);
|
||||
GDBStubUpdate(stub, 0);
|
||||
}
|
||||
|
||||
static void _ack(struct GDBStub* stub) {
|
||||
|
@ -254,6 +249,7 @@ static void _writeHostInfo(struct GDBStub* stub) {
|
|||
static void _continue(struct GDBStub* stub, const char* message) {
|
||||
mDebuggerModuleSetNeedsCallback(&stub->d);
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
stub->d.isPaused = false;
|
||||
// TODO: parse message
|
||||
UNUSED(message);
|
||||
}
|
||||
|
@ -791,7 +787,6 @@ void GDBStubCreate(struct GDBStub* stub) {
|
|||
stub->d.type = DEBUGGER_GDB;
|
||||
stub->untilPoll = GDB_STUB_INTERVAL;
|
||||
stub->lineAck = GDB_ACK_PENDING;
|
||||
stub->shouldBlock = false;
|
||||
}
|
||||
|
||||
bool GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress, enum GDBWatchpointsBehvaior watchpointsBehavior) {
|
||||
|
@ -841,17 +836,17 @@ void GDBStubShutdown(struct GDBStub* stub) {
|
|||
}
|
||||
}
|
||||
|
||||
void GDBStubUpdate(struct GDBStub* stub) {
|
||||
bool GDBStubUpdate(struct GDBStub* stub, int32_t timeoutMs) {
|
||||
if (stub->socket == INVALID_SOCKET) {
|
||||
stub->d.needsCallback = false;
|
||||
stub->d.isPaused = false;
|
||||
mDebuggerUpdatePaused(stub->d.p);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (stub->connection == INVALID_SOCKET) {
|
||||
if (stub->shouldBlock) {
|
||||
if (timeoutMs) {
|
||||
Socket reads = stub->socket;
|
||||
SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
|
||||
SocketPoll(1, &reads, 0, 0, timeoutMs);
|
||||
}
|
||||
stub->connection = SocketAccept(stub->socket, 0);
|
||||
if (!SOCKET_FAILED(stub->connection)) {
|
||||
|
@ -860,36 +855,38 @@ void GDBStubUpdate(struct GDBStub* stub) {
|
|||
}
|
||||
mDebuggerEnter(stub->d.p, DEBUGGER_ENTER_ATTACHED, 0);
|
||||
} else if (SocketWouldBlock()) {
|
||||
return;
|
||||
return false;
|
||||
} else {
|
||||
goto connectionLost;
|
||||
}
|
||||
SocketSetTCPPush(stub->connection, 1);
|
||||
}
|
||||
while (true) {
|
||||
if (stub->shouldBlock) {
|
||||
Socket reads = stub->connection;
|
||||
SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT);
|
||||
}
|
||||
ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
|
||||
if (messageLen == 0) {
|
||||
goto connectionLost;
|
||||
}
|
||||
if (messageLen == -1) {
|
||||
if (SocketWouldBlock()) {
|
||||
return;
|
||||
}
|
||||
goto connectionLost;
|
||||
}
|
||||
stub->line[messageLen] = '\0';
|
||||
mLOG(DEBUGGER, DEBUG, "< %s", stub->line);
|
||||
ssize_t position = 0;
|
||||
while (position < messageLen) {
|
||||
position += _parseGDBMessage(stub, &stub->line[position]);
|
||||
}
|
||||
|
||||
if (timeoutMs) {
|
||||
Socket reads = stub->connection;
|
||||
SocketPoll(1, &reads, 0, 0, timeoutMs);
|
||||
}
|
||||
ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
|
||||
if (messageLen == 0) {
|
||||
goto connectionLost;
|
||||
}
|
||||
if (messageLen == -1) {
|
||||
if (SocketWouldBlock()) {
|
||||
return false;
|
||||
}
|
||||
goto connectionLost;
|
||||
}
|
||||
|
||||
stub->line[messageLen] = '\0';
|
||||
mLOG(DEBUGGER, DEBUG, "< %s", stub->line);
|
||||
ssize_t position = 0;
|
||||
while (position < messageLen) {
|
||||
position += _parseGDBMessage(stub, &stub->line[position]);
|
||||
}
|
||||
return true;
|
||||
|
||||
connectionLost:
|
||||
mLOG(DEBUGGER, WARN, "Connection lost");
|
||||
GDBStubHangup(stub);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,12 +7,31 @@
|
|||
|
||||
#include <mgba/core/config.h>
|
||||
#include <mgba/core/version.h>
|
||||
#include <mgba-util/threading.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
struct CLIDebuggerEditLineBackend {
|
||||
struct CLIDebuggerBackend d;
|
||||
|
||||
EditLine* elstate;
|
||||
History* histate;
|
||||
|
||||
int count;
|
||||
const char* prompt;
|
||||
bool doPrompt;
|
||||
Thread promptThread;
|
||||
Mutex promptMutex;
|
||||
Condition promptRead;
|
||||
Condition promptWrite;
|
||||
bool exitThread;
|
||||
};
|
||||
|
||||
static struct CLIDebugger* _activeDebugger;
|
||||
|
||||
static THREAD_ENTRY _promptThread(void*);
|
||||
|
||||
static char* _prompt(EditLine* el) {
|
||||
UNUSED(el);
|
||||
return "> ";
|
||||
|
@ -43,7 +62,7 @@ static unsigned char _tabComplete(EditLine* elstate, int ch) {
|
|||
}
|
||||
|
||||
ATTRIBUTE_FORMAT(printf, 2, 3)
|
||||
void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
|
||||
static void CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
|
||||
UNUSED(be);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
@ -51,7 +70,7 @@ void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt,
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
|
||||
static void CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
// TODO: get argv[0]
|
||||
elbe->elstate = el_init(binaryName, stdin, stdout, stderr);
|
||||
|
@ -81,12 +100,26 @@ void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
|
|||
}
|
||||
}
|
||||
|
||||
MutexInit(&elbe->promptMutex);
|
||||
ConditionInit(&elbe->promptRead);
|
||||
ConditionInit(&elbe->promptWrite);
|
||||
elbe->prompt = NULL;
|
||||
elbe->exitThread = false;
|
||||
elbe->doPrompt = false;
|
||||
ThreadCreate(&elbe->promptThread, _promptThread, elbe);
|
||||
|
||||
_activeDebugger = be->p;
|
||||
signal(SIGINT, _breakIntoDefault);
|
||||
}
|
||||
|
||||
void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
|
||||
static void CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
MutexLock(&elbe->promptMutex);
|
||||
elbe->exitThread = true;
|
||||
ConditionWake(&elbe->promptWrite);
|
||||
MutexUnlock(&elbe->promptMutex);
|
||||
ThreadJoin(&elbe->promptThread);
|
||||
|
||||
char path[PATH_MAX + 1];
|
||||
mCoreConfigDirectory(path, PATH_MAX);
|
||||
if (path[0]) {
|
||||
|
@ -111,11 +144,51 @@ void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
|
|||
free(elbe);
|
||||
}
|
||||
|
||||
const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
static THREAD_ENTRY _promptThread(void* context) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = context;
|
||||
|
||||
MutexLock(&elbe->promptMutex);
|
||||
while (!elbe->exitThread) {
|
||||
if (elbe->doPrompt) {
|
||||
MutexUnlock(&elbe->promptMutex);
|
||||
elbe->prompt = el_gets(elbe->elstate, &elbe->count);
|
||||
MutexLock(&elbe->promptMutex);
|
||||
elbe->doPrompt = false;
|
||||
ConditionWake(&elbe->promptRead);
|
||||
}
|
||||
ConditionWait(&elbe->promptWrite, &elbe->promptMutex);
|
||||
}
|
||||
MutexUnlock(&elbe->promptMutex);
|
||||
}
|
||||
|
||||
static int CLIDebuggerEditLinePoll(struct CLIDebuggerBackend* be, int32_t timeoutMs) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
int gotPrompt = 0;
|
||||
MutexLock(&elbe->promptMutex);
|
||||
if (!elbe->prompt) {
|
||||
elbe->doPrompt = true;
|
||||
ConditionWake(&elbe->promptWrite);
|
||||
ConditionWaitTimed(&elbe->promptRead, &elbe->promptMutex, timeoutMs);
|
||||
}
|
||||
if (elbe->prompt) {
|
||||
gotPrompt = 1;
|
||||
}
|
||||
MutexUnlock(&elbe->promptMutex);
|
||||
|
||||
return gotPrompt;
|
||||
}
|
||||
|
||||
static const char* CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
int count;
|
||||
*len = 0;
|
||||
const char* line = el_gets(elbe->elstate, &count);
|
||||
if (CLIDebuggerEditLinePoll(be, -1) != 1) {
|
||||
return NULL;
|
||||
}
|
||||
MutexLock(&elbe->promptMutex);
|
||||
int count = elbe->count;
|
||||
const char* line = elbe->prompt;
|
||||
elbe->prompt = NULL;
|
||||
MutexUnlock(&elbe->promptMutex);
|
||||
if (line) {
|
||||
if (count > 1) {
|
||||
// Crop off newline
|
||||
|
@ -126,12 +199,13 @@ const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t*
|
|||
}
|
||||
return line;
|
||||
}
|
||||
void _CLIDebuggerEditLineLineAppend(struct CLIDebuggerBackend* be, const char* line) {
|
||||
|
||||
static void CLIDebuggerEditLineLineAppend(struct CLIDebuggerBackend* be, const char* line) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
el_insertstr(elbe->elstate, line);
|
||||
}
|
||||
|
||||
const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
static const char* CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
HistEvent ev;
|
||||
if (history(elbe->histate, &ev, H_FIRST) < 0) {
|
||||
|
@ -148,7 +222,7 @@ const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_
|
|||
return ev.str;
|
||||
}
|
||||
|
||||
void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char* line) {
|
||||
static void CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char* line) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
|
||||
HistEvent ev;
|
||||
history(elbe->histate, &ev, H_ENTER, line);
|
||||
|
@ -156,13 +230,14 @@ void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char
|
|||
|
||||
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
|
||||
struct CLIDebuggerEditLineBackend* elbe = calloc(1, sizeof(*elbe));
|
||||
elbe->d.printf = _CLIDebuggerEditLinePrintf;
|
||||
elbe->d.init = _CLIDebuggerEditLineInit;
|
||||
elbe->d.deinit = _CLIDebuggerEditLineDeinit;
|
||||
elbe->d.readline = _CLIDebuggerEditLineReadLine;
|
||||
elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend;
|
||||
elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast;
|
||||
elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend;
|
||||
elbe->d.printf = CLIDebuggerEditLinePrintf;
|
||||
elbe->d.init = CLIDebuggerEditLineInit;
|
||||
elbe->d.deinit = CLIDebuggerEditLineDeinit;
|
||||
elbe->d.poll = CLIDebuggerEditLinePoll;
|
||||
elbe->d.readline = CLIDebuggerEditLineReadLine;
|
||||
elbe->d.lineAppend = CLIDebuggerEditLineLineAppend;
|
||||
elbe->d.historyLast = CLIDebuggerEditLineHistoryLast;
|
||||
elbe->d.historyAppend = CLIDebuggerEditLineHistoryAppend;
|
||||
elbe->d.interrupt = NULL;
|
||||
return &elbe->d;
|
||||
}
|
||||
|
|
|
@ -14,13 +14,6 @@ CXX_GUARD_START
|
|||
|
||||
#include <histedit.h>
|
||||
|
||||
struct CLIDebuggerEditLineBackend {
|
||||
struct CLIDebuggerBackend d;
|
||||
|
||||
EditLine* elstate;
|
||||
History* histate;
|
||||
};
|
||||
|
||||
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
|
|
@ -22,6 +22,7 @@ DebuggerConsoleController::DebuggerConsoleController(QObject* parent)
|
|||
m_backend.printf = printf;
|
||||
m_backend.init = init;
|
||||
m_backend.deinit = deinit;
|
||||
m_backend.poll = poll;
|
||||
m_backend.readline = readLine;
|
||||
m_backend.lineAppend = lineAppend;
|
||||
m_backend.historyLast = historyLast;
|
||||
|
@ -88,6 +89,14 @@ void DebuggerConsoleController::deinit(struct CLIDebuggerBackend* be) {
|
|||
}
|
||||
}
|
||||
|
||||
int DebuggerConsoleController::poll(struct CLIDebuggerBackend* be, int32_t timeoutMs) {
|
||||
Backend* consoleBe = reinterpret_cast<Backend*>(be);
|
||||
DebuggerConsoleController* self = consoleBe->self;
|
||||
QMutexLocker lock(&self->m_mutex);
|
||||
self->m_cond.wait(&self->m_mutex, timeoutMs < 0 ? ULONG_MAX : static_cast<unsigned long>(timeoutMs));
|
||||
return !self->m_lines.isEmpty();
|
||||
}
|
||||
|
||||
const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) {
|
||||
Backend* consoleBe = reinterpret_cast<Backend*>(be);
|
||||
DebuggerConsoleController* self = consoleBe->self;
|
||||
|
@ -137,10 +146,6 @@ void DebuggerConsoleController::interrupt(struct CLIDebuggerBackend* be) {
|
|||
DebuggerConsoleController* self = consoleBe->self;
|
||||
QMutexLocker lock(&self->m_mutex);
|
||||
self->m_cond.wakeOne();
|
||||
if (!self->m_lines.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
self->m_lines.append("\033");
|
||||
}
|
||||
|
||||
void DebuggerConsoleController::historyLoad() {
|
||||
|
|
|
@ -42,6 +42,7 @@ private:
|
|||
static void printf(struct CLIDebuggerBackend* be, const char* fmt, ...);
|
||||
static void init(struct CLIDebuggerBackend* be);
|
||||
static void deinit(struct CLIDebuggerBackend* be);
|
||||
static int poll(struct CLIDebuggerBackend* be, int32_t timeoutMs);
|
||||
static const char* readLine(struct CLIDebuggerBackend* be, size_t* len);
|
||||
static void lineAppend(struct CLIDebuggerBackend* be, const char* line);
|
||||
static const char* historyLast(struct CLIDebuggerBackend* be, size_t* len);
|
||||
|
|
Loading…
Reference in New Issue