Debugger: Add debugger polling to avoid blocking

This commit is contained in:
Vicki Pfau 2023-05-09 21:26:23 -07:00
parent a00f2939ad
commit 257122796c
10 changed files with 155 additions and 76 deletions

View File

@ -152,7 +152,7 @@ struct mDebuggerModule {
void (*init)(struct mDebuggerModule*); void (*init)(struct mDebuggerModule*);
void (*deinit)(struct mDebuggerModule*); void (*deinit)(struct mDebuggerModule*);
void (*paused)(struct mDebuggerModule*); void (*paused)(struct mDebuggerModule*, int32_t timeoutMs);
void (*update)(struct mDebuggerModule*); void (*update)(struct mDebuggerModule*);
void (*entered)(struct mDebuggerModule*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); void (*entered)(struct mDebuggerModule*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);
void (*custom)(struct mDebuggerModule*); void (*custom)(struct mDebuggerModule*);
@ -166,6 +166,7 @@ void mDebuggerDeinit(struct mDebugger*);
void mDebuggerAttach(struct mDebugger*, struct mCore*); void mDebuggerAttach(struct mDebugger*, struct mCore*);
void mDebuggerAttachModule(struct mDebugger*, struct mDebuggerModule*); void mDebuggerAttachModule(struct mDebugger*, struct mDebuggerModule*);
void mDebuggerDetachModule(struct mDebugger*, struct mDebuggerModule*); void mDebuggerDetachModule(struct mDebugger*, struct mDebuggerModule*);
void mDebuggerRunTimeout(struct mDebugger* debugger, int32_t timeoutMs);
void mDebuggerRun(struct mDebugger*); void mDebuggerRun(struct mDebugger*);
void mDebuggerRunFrame(struct mDebugger*); void mDebuggerRunFrame(struct mDebugger*);
void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*);

View File

@ -73,6 +73,7 @@ struct CLIDebuggerBackend {
ATTRIBUTE_FORMAT(printf, 2, 3) ATTRIBUTE_FORMAT(printf, 2, 3)
void (*printf)(struct CLIDebuggerBackend*, const char* fmt, ...); void (*printf)(struct CLIDebuggerBackend*, const char* fmt, ...);
int (*poll)(struct CLIDebuggerBackend*, int32_t timeoutMs);
const char* (*readline)(struct CLIDebuggerBackend*, size_t* len); const char* (*readline)(struct CLIDebuggerBackend*, size_t* len);
void (*lineAppend)(struct CLIDebuggerBackend*, const char* line); void (*lineAppend)(struct CLIDebuggerBackend*, const char* line);
const char* (*historyLast)(struct CLIDebuggerBackend*, size_t* len); const char* (*historyLast)(struct CLIDebuggerBackend*, size_t* len);

View File

@ -41,7 +41,6 @@ struct GDBStub {
Socket socket; Socket socket;
Socket connection; Socket connection;
bool shouldBlock;
int untilPoll; int untilPoll;
bool supportsSwbreak; bool supportsSwbreak;
@ -56,7 +55,7 @@ bool GDBStubListen(struct GDBStub*, int port, const struct Address* bindAddress,
void GDBStubHangup(struct GDBStub*); void GDBStubHangup(struct GDBStub*);
void GDBStubShutdown(struct GDBStub*); void GDBStubShutdown(struct GDBStub*);
void GDBStubUpdate(struct GDBStub*); bool GDBStubUpdate(struct GDBStub*, int timeoutMs);
CXX_GUARD_END CXX_GUARD_END

View File

@ -1092,7 +1092,7 @@ bool CLIDebuggerRunCommand(struct CLIDebugger* debugger, const char* line, size_
return false; return false;
} }
static void _commandLine(struct mDebuggerModule* debugger) { static void _commandLine(struct mDebuggerModule* debugger, int32_t timeoutMs) {
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
const char* line; const char* line;
size_t len; size_t len;
@ -1102,15 +1102,20 @@ static void _commandLine(struct mDebuggerModule* debugger) {
_printStatus(cliDebugger, 0); _printStatus(cliDebugger, 0);
} }
while (debugger->isPaused && !mDebuggerIsShutdown(debugger->p)) { 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); line = cliDebugger->backend->readline(cliDebugger->backend, &len);
if (!line || len == 0) { if (!line || len == 0) {
mDebuggerShutdown(debugger->p); mDebuggerShutdown(debugger->p);
return; return;
} }
if (line[0] == '\033') {
cliDebugger->skipStatus = true;
return;
}
if (line[0] == '\n') { if (line[0] == '\n') {
line = cliDebugger->backend->historyLast(cliDebugger->backend, &len); line = cliDebugger->backend->historyLast(cliDebugger->backend, &len);
if (line && len) { if (line && len) {

View File

@ -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 i;
size_t anyPaused = 0; size_t anyPaused = 0;
@ -146,7 +146,7 @@ void mDebuggerRun(struct mDebugger* debugger) {
struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i);
if (module->isPaused) { if (module->isPaused) {
if (module->paused) { if (module->paused) {
module->paused(module); module->paused(module, timeoutMs);
} }
if (module->isPaused) { if (module->isPaused) {
++anyPaused; ++anyPaused;
@ -167,6 +167,10 @@ void mDebuggerRun(struct mDebugger* debugger) {
} }
} }
void mDebuggerRun(struct mDebugger* debugger) {
mDebuggerRunTimeout(debugger, 50);
}
void mDebuggerRunFrame(struct mDebugger* debugger) { void mDebuggerRunFrame(struct mDebugger* debugger) {
uint32_t frame = debugger->core->frameCounter(debugger->core); uint32_t frame = debugger->core->frameCounter(debugger->core);
do { do {
@ -309,7 +313,5 @@ bool mDebuggerLookupIdentifier(struct mDebugger* debugger, const char* name, int
void mDebuggerModuleSetNeedsCallback(struct mDebuggerModule* debugger) { void mDebuggerModuleSetNeedsCallback(struct mDebuggerModule* debugger) {
debugger->needsCallback = true; debugger->needsCallback = true;
if (debugger->p->state == DEBUGGER_RUNNING) { mDebuggerUpdatePaused(debugger->p);
debugger->p->state = DEBUGGER_CALLBACK;
}
} }

View File

@ -17,8 +17,6 @@
#define SIGTRAP 5 /* Win32 Signals do not include SIGTRAP */ #define SIGTRAP 5 /* Win32 Signals do not include SIGTRAP */
#endif #endif
#define SOCKET_TIMEOUT 50
enum GDBError { enum GDBError {
GDB_NO_ERROR = 0x00, GDB_NO_ERROR = 0x00,
GDB_BAD_ARGUMENTS = 0x06, GDB_BAD_ARGUMENTS = 0x06,
@ -135,20 +133,17 @@ static void _gdbStubPoll(struct mDebuggerModule* debugger) {
return; return;
} }
stub->untilPoll = GDB_STUB_INTERVAL; stub->untilPoll = GDB_STUB_INTERVAL;
stub->shouldBlock = false; GDBStubUpdate(stub, 0);
GDBStubUpdate(stub);
} }
static void _gdbStubWait(struct mDebuggerModule* debugger) { static void _gdbStubWait(struct mDebuggerModule* debugger, int32_t timeoutMs) {
struct GDBStub* stub = (struct GDBStub*) debugger; struct GDBStub* stub = (struct GDBStub*) debugger;
stub->shouldBlock = true; GDBStubUpdate(stub, timeoutMs);
GDBStubUpdate(stub);
} }
static void _gdbStubUpdate(struct mDebuggerModule* debugger) { static void _gdbStubUpdate(struct mDebuggerModule* debugger) {
struct GDBStub* stub = (struct GDBStub*) debugger; struct GDBStub* stub = (struct GDBStub*) debugger;
stub->shouldBlock = false; GDBStubUpdate(stub, 0);
GDBStubUpdate(stub);
} }
static void _ack(struct GDBStub* stub) { 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) { static void _continue(struct GDBStub* stub, const char* message) {
mDebuggerModuleSetNeedsCallback(&stub->d); mDebuggerModuleSetNeedsCallback(&stub->d);
stub->untilPoll = GDB_STUB_INTERVAL; stub->untilPoll = GDB_STUB_INTERVAL;
stub->d.isPaused = false;
// TODO: parse message // TODO: parse message
UNUSED(message); UNUSED(message);
} }
@ -791,7 +787,6 @@ void GDBStubCreate(struct GDBStub* stub) {
stub->d.type = DEBUGGER_GDB; stub->d.type = DEBUGGER_GDB;
stub->untilPoll = GDB_STUB_INTERVAL; stub->untilPoll = GDB_STUB_INTERVAL;
stub->lineAck = GDB_ACK_PENDING; stub->lineAck = GDB_ACK_PENDING;
stub->shouldBlock = false;
} }
bool GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress, enum GDBWatchpointsBehvaior watchpointsBehavior) { 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) { if (stub->socket == INVALID_SOCKET) {
stub->d.needsCallback = false; stub->d.needsCallback = false;
stub->d.isPaused = false; stub->d.isPaused = false;
mDebuggerUpdatePaused(stub->d.p); mDebuggerUpdatePaused(stub->d.p);
return; return false;
} }
if (stub->connection == INVALID_SOCKET) { if (stub->connection == INVALID_SOCKET) {
if (stub->shouldBlock) { if (timeoutMs) {
Socket reads = stub->socket; Socket reads = stub->socket;
SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT); SocketPoll(1, &reads, 0, 0, timeoutMs);
} }
stub->connection = SocketAccept(stub->socket, 0); stub->connection = SocketAccept(stub->socket, 0);
if (!SOCKET_FAILED(stub->connection)) { if (!SOCKET_FAILED(stub->connection)) {
@ -860,36 +855,38 @@ void GDBStubUpdate(struct GDBStub* stub) {
} }
mDebuggerEnter(stub->d.p, DEBUGGER_ENTER_ATTACHED, 0); mDebuggerEnter(stub->d.p, DEBUGGER_ENTER_ATTACHED, 0);
} else if (SocketWouldBlock()) { } else if (SocketWouldBlock()) {
return; return false;
} else { } else {
goto connectionLost; goto connectionLost;
} }
SocketSetTCPPush(stub->connection, 1); SocketSetTCPPush(stub->connection, 1);
} }
while (true) {
if (stub->shouldBlock) { if (timeoutMs) {
Socket reads = stub->connection; Socket reads = stub->connection;
SocketPoll(1, &reads, 0, 0, SOCKET_TIMEOUT); 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;
}
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]);
}
} }
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: connectionLost:
mLOG(DEBUGGER, WARN, "Connection lost"); mLOG(DEBUGGER, WARN, "Connection lost");
GDBStubHangup(stub); GDBStubHangup(stub);
return false;
} }

View File

@ -7,12 +7,31 @@
#include <mgba/core/config.h> #include <mgba/core/config.h>
#include <mgba/core/version.h> #include <mgba/core/version.h>
#include <mgba-util/threading.h>
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
#include <signal.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 struct CLIDebugger* _activeDebugger;
static THREAD_ENTRY _promptThread(void*);
static char* _prompt(EditLine* el) { static char* _prompt(EditLine* el) {
UNUSED(el); UNUSED(el);
return "> "; return "> ";
@ -43,7 +62,7 @@ static unsigned char _tabComplete(EditLine* elstate, int ch) {
} }
ATTRIBUTE_FORMAT(printf, 2, 3) ATTRIBUTE_FORMAT(printf, 2, 3)
void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) { static void CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
UNUSED(be); UNUSED(be);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -51,7 +70,7 @@ void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt,
va_end(args); va_end(args);
} }
void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) { static void CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
// TODO: get argv[0] // TODO: get argv[0]
elbe->elstate = el_init(binaryName, stdin, stdout, stderr); 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; _activeDebugger = be->p;
signal(SIGINT, _breakIntoDefault); signal(SIGINT, _breakIntoDefault);
} }
void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) { static void CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) 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]; char path[PATH_MAX + 1];
mCoreConfigDirectory(path, PATH_MAX); mCoreConfigDirectory(path, PATH_MAX);
if (path[0]) { if (path[0]) {
@ -111,11 +144,51 @@ void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
free(elbe); 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; struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
int count;
*len = 0; *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 (line) {
if (count > 1) { if (count > 1) {
// Crop off newline // Crop off newline
@ -126,12 +199,13 @@ const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t*
} }
return line; 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; struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
el_insertstr(elbe->elstate, line); 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; struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
HistEvent ev; HistEvent ev;
if (history(elbe->histate, &ev, H_FIRST) < 0) { if (history(elbe->histate, &ev, H_FIRST) < 0) {
@ -148,7 +222,7 @@ const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_
return ev.str; 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; struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
HistEvent ev; HistEvent ev;
history(elbe->histate, &ev, H_ENTER, line); history(elbe->histate, &ev, H_ENTER, line);
@ -156,13 +230,14 @@ void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) { struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
struct CLIDebuggerEditLineBackend* elbe = calloc(1, sizeof(*elbe)); struct CLIDebuggerEditLineBackend* elbe = calloc(1, sizeof(*elbe));
elbe->d.printf = _CLIDebuggerEditLinePrintf; elbe->d.printf = CLIDebuggerEditLinePrintf;
elbe->d.init = _CLIDebuggerEditLineInit; elbe->d.init = CLIDebuggerEditLineInit;
elbe->d.deinit = _CLIDebuggerEditLineDeinit; elbe->d.deinit = CLIDebuggerEditLineDeinit;
elbe->d.readline = _CLIDebuggerEditLineReadLine; elbe->d.poll = CLIDebuggerEditLinePoll;
elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend; elbe->d.readline = CLIDebuggerEditLineReadLine;
elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast; elbe->d.lineAppend = CLIDebuggerEditLineLineAppend;
elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend; elbe->d.historyLast = CLIDebuggerEditLineHistoryLast;
elbe->d.historyAppend = CLIDebuggerEditLineHistoryAppend;
elbe->d.interrupt = NULL; elbe->d.interrupt = NULL;
return &elbe->d; return &elbe->d;
} }

View File

@ -14,13 +14,6 @@ CXX_GUARD_START
#include <histedit.h> #include <histedit.h>
struct CLIDebuggerEditLineBackend {
struct CLIDebuggerBackend d;
EditLine* elstate;
History* histate;
};
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void); struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void);
CXX_GUARD_END CXX_GUARD_END

View File

@ -22,6 +22,7 @@ DebuggerConsoleController::DebuggerConsoleController(QObject* parent)
m_backend.printf = printf; m_backend.printf = printf;
m_backend.init = init; m_backend.init = init;
m_backend.deinit = deinit; m_backend.deinit = deinit;
m_backend.poll = poll;
m_backend.readline = readLine; m_backend.readline = readLine;
m_backend.lineAppend = lineAppend; m_backend.lineAppend = lineAppend;
m_backend.historyLast = historyLast; 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) { const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) {
Backend* consoleBe = reinterpret_cast<Backend*>(be); Backend* consoleBe = reinterpret_cast<Backend*>(be);
DebuggerConsoleController* self = consoleBe->self; DebuggerConsoleController* self = consoleBe->self;
@ -137,10 +146,6 @@ void DebuggerConsoleController::interrupt(struct CLIDebuggerBackend* be) {
DebuggerConsoleController* self = consoleBe->self; DebuggerConsoleController* self = consoleBe->self;
QMutexLocker lock(&self->m_mutex); QMutexLocker lock(&self->m_mutex);
self->m_cond.wakeOne(); self->m_cond.wakeOne();
if (!self->m_lines.isEmpty()) {
return;
}
self->m_lines.append("\033");
} }
void DebuggerConsoleController::historyLoad() { void DebuggerConsoleController::historyLoad() {

View File

@ -42,6 +42,7 @@ private:
static void printf(struct CLIDebuggerBackend* be, const char* fmt, ...); static void printf(struct CLIDebuggerBackend* be, const char* fmt, ...);
static void init(struct CLIDebuggerBackend* be); static void init(struct CLIDebuggerBackend* be);
static void deinit(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 const char* readLine(struct CLIDebuggerBackend* be, size_t* len);
static void lineAppend(struct CLIDebuggerBackend* be, const char* line); static void lineAppend(struct CLIDebuggerBackend* be, const char* line);
static const char* historyLast(struct CLIDebuggerBackend* be, size_t* len); static const char* historyLast(struct CLIDebuggerBackend* be, size_t* len);