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 {
connNotifier.wait();
synchronized (connNotifier) {
connNotifier.wait();
}
}
public void run(InetSocketAddress address) {

View File

@ -1032,15 +1032,20 @@ public class SimpleDebugger implements Debugger {
}
mappings.put(body, map);
}
private boolean instructionLock;
@Override public boolean onInstruction(Environment env, Frame cf, Instruction instruction, Value returnVal, EngineException error, boolean caught) {
if (!enabled) return false;
if (instructionLock) return false;
instructionLock = true;
boolean isBreakpointable;
Location loc;
DebugFrame frame;
BreakpointType bptType;
try {
boolean isBreakpointable;
Location loc;
DebugFrame frame;
BreakpointType bptType;
synchronized (this) {
frame = getFrame(cf);
var map = DebugContext.get(env).getMap(frame.frame.function);
@ -1077,49 +1082,55 @@ public class SimpleDebugger implements Debugger {
instruction.params.length == 1 &&
instruction.get(0).equals("debug")
) pauseDebug(env, null);
}
while (enabled) {
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 {
synchronized (updateNotifier) {
updateNotifier.wait();
while (enabled) {
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 {
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) {
var prevFrame = currFrame;