GP-690: Protecting model/manager threads from user callbacks.

This commit is contained in:
Dan 2021-02-12 14:59:44 -05:00
parent 2ed29f5693
commit 56f3f5c656
7 changed files with 87 additions and 24 deletions

View file

@ -18,6 +18,7 @@ package ghidra.dbg;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import ghidra.async.AsyncUtils;
import ghidra.async.TypeSpec;
@ -501,4 +502,11 @@ public interface DebuggerObjectModel {
Msg.error(origin, message, ex);
}
}
/**
* Get the executor used to invoke client callback routines
*
* @return the executor
*/
Executor getClientExecutor();
}

View file

@ -15,12 +15,16 @@
*/
package ghidra.dbg.agent;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import ghidra.dbg.DebuggerModelListener;
import ghidra.util.datastruct.ListenerSet;
public abstract class AbstractDebuggerObjectModel implements SpiDebuggerObjectModel {
protected final Executor clientExecutor = Executors.newSingleThreadExecutor();
protected final ListenerSet<DebuggerModelListener> listeners =
new ListenerSet<>(DebuggerModelListener.class);
new ListenerSet<>(DebuggerModelListener.class, clientExecutor);
@Override
public void addModelListener(DebuggerModelListener listener) {
@ -31,4 +35,9 @@ public abstract class AbstractDebuggerObjectModel implements SpiDebuggerObjectMo
public void removeModelListener(DebuggerModelListener listener) {
listeners.remove(listener);
}
@Override
public Executor getClientExecutor() {
return clientExecutor;
}
}

View file

@ -55,11 +55,11 @@ public abstract class AbstractTargetObject<P extends TargetObject>
protected boolean valid = true;
protected final ListenerSet<TargetObjectListener> listeners =
new ListenerSet<>(TargetObjectListener.class);
protected final ListenerSet<TargetObjectListener> listeners;
public AbstractTargetObject(DebuggerObjectModel model, P parent, String key, String typeHint,
TargetObjectSchema schema) {
this.listeners = new ListenerSet<>(TargetObjectListener.class, model.getClientExecutor());
this.model = model;
this.parent = parent;
this.completedParent = CompletableFuture.completedFuture(parent);