mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Reply to every debugger request, even the ones that finish later
Eight events answered nothing at all: cpu.stepping, cpu.resume, gpu.stats.feed
and the five stepping requests. Their documented contract was "no immediate
response, an event follows", which leaves a client unable to tell an accepted
request from one that was dropped - and forces any request/response
correlation to carry a hardcoded list of events that don't answer. wsdbg's
--sync doesn't have that list, so it waits for the next message and treats
whatever broadcast arrives first as the answer, silently misattributing every
later response in the script.
Fixed centrally in the dispatch loop rather than in the eight handlers: if a
handler finishes without having sent anything, send an empty response carrying
its ticket. That also covers handlers added later, which is the part a
per-handler fix wouldn't.
The asynchronous event that reports the real outcome is unchanged and still
follows. The two are easy to tell apart - the acknowledgement carries the
ticket from the request, a broadcast has none:
-> {"event":"cpu.stepInto","ticket":3}
<- {"event":"cpu.stepInto","ticket":3}
<- {"event":"cpu.stepping","pc":142622896,"reason":"cpu.stepInto",...}
Existing clients ignore events they didn't ask for, and this adds a message
rather than changing or removing one, so nothing that worked before breaks.
pspautotests 314/314.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
This commit is contained in:
1 parent
8120338530
commit
ef426c8f82
5 files changed
+32
-13
No files matched your search
@@ -85,7 +85,8 @@ static DebugInterface *CPUFromRequest(DebuggerRequest &req, uint32_t *threadID =
|
||||
// Parameters:
|
||||
// - thread: optional number indicating the thread id to plan stepping on.
|
||||
//
|
||||
// No immediate response on success. A cpu.stepping event will be sent once complete.
|
||||
// Response (same event name) with no extra data on success. A cpu.stepping event follows once
|
||||
// the step completes.
|
||||
// May fail (same-thread case only) if another step/run request is already pending this host
|
||||
// frame - safe to retry shortly after.
|
||||
//
|
||||
@@ -114,11 +115,10 @@ void WebSocketSteppingState::Into(DebuggerRequest &req) {
|
||||
g_breakpoints.SetSkipFirst(currentMIPS->pc);
|
||||
|
||||
// Core_RequestCPUStep() can fail (a step or run request is already queued this host
|
||||
// frame - see its own "Can't submit two steps in one host frame" log). Previously
|
||||
// unchecked here: on failure, no step ever happens and no cpu.stepping event ever
|
||||
// fires, but the client got no response either (this event's contract is "no
|
||||
// immediate response, a cpu.stepping event follows") - so a rejected step looked
|
||||
// identical to one that's just still in flight, indefinitely. Surface it instead.
|
||||
// frame - see its own "Can't submit two steps in one host frame" log). On failure no
|
||||
// step ever happens and no cpu.stepping event ever fires, so a rejected step would
|
||||
// otherwise be indistinguishable from one still in flight - the acknowledgement every
|
||||
// request now gets doesn't tell those apart. Surface it as an error instead.
|
||||
if (!Core_RequestCPUStep(CPUStepType::Into)) {
|
||||
req.Fail("Could not step: a step or run request is already pending");
|
||||
return;
|
||||
@@ -145,7 +145,7 @@ void WebSocketSteppingState::Into(DebuggerRequest &req) {
|
||||
// Parameters:
|
||||
// - thread: optional number indicating the thread id to plan stepping on.
|
||||
//
|
||||
// No immediate response. A cpu.stepping event will be sent once complete.
|
||||
// Response (same event name) with no extra data. A cpu.stepping event follows once complete.
|
||||
//
|
||||
// Note: any thread can wake the cpu when it hits the next instruction currently.
|
||||
void WebSocketSteppingState::Over(DebuggerRequest &req) {
|
||||
@@ -200,7 +200,7 @@ void WebSocketSteppingState::Over(DebuggerRequest &req) {
|
||||
// Parameters:
|
||||
// - thread: optional number indicating the thread id to plan stepping on.
|
||||
//
|
||||
// No immediate response. A cpu.stepping event will be sent once complete.
|
||||
// Response (same event name) with no extra data. A cpu.stepping event follows once complete.
|
||||
//
|
||||
// Note: any thread can wake the cpu when it hits the next instruction currently.
|
||||
void WebSocketSteppingState::Out(DebuggerRequest &req) {
|
||||
@@ -253,7 +253,7 @@ void WebSocketSteppingState::Out(DebuggerRequest &req) {
|
||||
// Parameters:
|
||||
// - address: number parameter for destination.
|
||||
//
|
||||
// No immediate response. A cpu.stepping event will be sent once complete.
|
||||
// Response (same event name) with no extra data. A cpu.stepping event follows once complete.
|
||||
void WebSocketSteppingState::RunUntil(DebuggerRequest &req) {
|
||||
if (!currentDebugMIPS->isAlive()) {
|
||||
return req.Fail("CPU not started");
|
||||
@@ -338,7 +338,7 @@ void WebSocketSteppingState::RunUntilTime(DebuggerRequest &req) {
|
||||
//
|
||||
// No parameters.
|
||||
//
|
||||
// No immediate response. A cpu.stepping event will be sent once complete.
|
||||
// Response (same event name) with no extra data. A cpu.stepping event follows once complete.
|
||||
void WebSocketSteppingState::HLE(DebuggerRequest &req) {
|
||||
if (!currentDebugMIPS->isAlive()) {
|
||||
return req.Fail("CPU not started");
|
||||
|
||||
Reference in new issue
Block a user