fix: debugger concurrency issues

This commit is contained in:
TopchetoEU 2024-12-28 13:19:53 +02:00
parent 4c53689d9c
commit 9ce0504948
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
2 changed files with 58 additions and 45 deletions

View File

@ -159,7 +159,9 @@ public class DebugServer {
} }
public void awaitConnection() throws InterruptedException { public void awaitConnection() throws InterruptedException {
connNotifier.wait(); synchronized (connNotifier) {
connNotifier.wait();
}
} }
public void run(InetSocketAddress address) { public void run(InetSocketAddress address) {

View File

@ -1032,15 +1032,20 @@ public class SimpleDebugger implements Debugger {
} }
mappings.put(body, map); mappings.put(body, map);
} }
private boolean instructionLock;
@Override public boolean onInstruction(Environment env, Frame cf, Instruction instruction, Value returnVal, EngineException error, boolean caught) { @Override public boolean onInstruction(Environment env, Frame cf, Instruction instruction, Value returnVal, EngineException error, boolean caught) {
if (!enabled) return false; if (!enabled) return false;
if (instructionLock) return false;
instructionLock = true;
boolean isBreakpointable; try {
Location loc; boolean isBreakpointable;
DebugFrame frame; Location loc;
BreakpointType bptType; DebugFrame frame;
BreakpointType bptType;
synchronized (this) {
frame = getFrame(cf); frame = getFrame(cf);
var map = DebugContext.get(env).getMap(frame.frame.function); var map = DebugContext.get(env).getMap(frame.frame.function);
@ -1077,49 +1082,55 @@ public class SimpleDebugger implements Debugger {
instruction.params.length == 1 && instruction.params.length == 1 &&
instruction.get(0).equals("debug") instruction.get(0).equals("debug")
) pauseDebug(env, null); ) pauseDebug(env, null);
}
while (enabled) {
synchronized (this) { synchronized (this) {
switch (state) {
case PAUSED_EXCEPTION:
case PAUSED_NORMAL: break;
case STEPPING_OUT:
case RESUMED: return false;
case STEPPING_IN:
case STEPPING_OVER:
if (stepOutFrame.frame == frame.frame) {
if (returnVal != null || error != null) {
state = State.STEPPING_OUT;
continue;
}
else if (stepOutPtr != frame.frame.codePtr) {
if (state == State.STEPPING_IN && bptType.shouldStepIn()) {
pauseDebug(env, null);
break;
}
else if (state == State.STEPPING_OVER && bptType.shouldStepOver()) {
pauseDebug(env, null);
break;
}
}
}
return false;
}
} }
try { while (enabled) {
synchronized (updateNotifier) { synchronized (this) {
updateNotifier.wait(); switch (state) {
case PAUSED_EXCEPTION:
case PAUSED_NORMAL: break;
case STEPPING_OUT:
case RESUMED: return false;
case STEPPING_IN:
case STEPPING_OVER:
if (stepOutFrame.frame == frame.frame) {
if (returnVal != null || error != null) {
state = State.STEPPING_OUT;
continue;
}
else if (stepOutPtr != frame.frame.codePtr) {
if (state == State.STEPPING_IN && bptType.shouldStepIn()) {
pauseDebug(env, null);
break;
}
else if (state == State.STEPPING_OVER && bptType.shouldStepOver()) {
pauseDebug(env, null);
break;
}
}
}
return false;
}
} }
try {
synchronized (updateNotifier) {
updateNotifier.wait();
}
}
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
} }
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
return false;
}
finally {
instructionLock = false;
} }
return false;
} }
@Override public synchronized void onFramePush(Environment env, Frame frame) { @Override public synchronized void onFramePush(Environment env, Frame frame) {
var prevFrame = currFrame; var prevFrame = currFrame;