GP-5314: Destroy LiveMemoryHandler

This commit is contained in:
Dan 2025-02-18 18:23:30 +00:00
parent 7c74de60e6
commit bef0660e6a
32 changed files with 667 additions and 783 deletions

View file

@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -17,6 +17,9 @@ package ghidra.app.plugin.core.debug.service.tracermi;
import ghidra.app.plugin.core.debug.service.tracermi.TraceRmiHandler.*;
import ghidra.debug.api.tracermi.TraceRmiError;
import ghidra.framework.data.DomainObjectAdapterDB;
import ghidra.framework.model.TransactionInfo;
import ghidra.framework.model.TransactionListener;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.rmi.trace.TraceRmi.*;
@ -29,12 +32,51 @@ class OpenTrace implements ValueDecoder {
final DoId doId;
final Trace trace;
final TraceRmiTarget target;
final CurrentTxListener txListener;
TraceSnapshot lastSnapshot;
class CurrentTxListener implements TransactionListener {
boolean undoable;
public void markNotUndoable() {
undoable = false;
}
@Override
public void transactionStarted(DomainObjectAdapterDB domainObj, TransactionInfo tx) {
undoable = true;
}
@Override
public void transactionEnded(DomainObjectAdapterDB domainObj) {
if (!undoable) {
trace.clearUndo();
}
}
@Override
public void undoStackChanged(DomainObjectAdapterDB domainObj) {
// NOP
}
@Override
public void undoRedoOccurred(DomainObjectAdapterDB domainObj) {
// NOP
}
}
OpenTrace(DoId doId, Trace trace, TraceRmiTarget target) {
this.doId = doId;
this.trace = trace;
this.target = target;
this.txListener = new CurrentTxListener();
trace.addTransactionListener(txListener);
}
public void dispose(TraceRmiHandler consumer) {
trace.removeTransactionListener(txListener);
trace.release(consumer);
}
public TraceSnapshot createSnapshot(Snap snap, String description) {
@ -55,7 +97,7 @@ class OpenTrace implements ValueDecoder {
TraceObject object =
trace.getObjectManager().getObjectByCanonicalPath(TraceRmiHandler.toKeyPath(path));
if (required && object == null) {
throw new InvalidObjPathError();
throw new InvalidObjPathError(path.getPath());
}
return object;
}
@ -78,7 +120,7 @@ class OpenTrace implements ValueDecoder {
public AddressSpace getSpace(String name, boolean required) {
AddressSpace space = trace.getBaseAddressFactory().getAddressSpace(name);
if (required && space == null) {
throw new NoSuchAddressSpaceError();
throw new NoSuchAddressSpaceError(name);
}
return space;
}

View file

@ -90,9 +90,15 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
}
protected static class InvalidObjPathError extends TraceRmiError {
public InvalidObjPathError(String path) {
super(path);
}
}
protected static class NoSuchAddressSpaceError extends TraceRmiError {
public NoSuchAddressSpaceError(String name) {
super(name);
}
}
protected static class InvalidSchemaError extends TraceRmiError {
@ -292,8 +298,8 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
synchronized (openTxes) {
while (!openTxes.isEmpty()) {
Tid nextKey = openTxes.keySet().iterator().next();
OpenTx open = openTxes.remove(nextKey);
open.tx.close();
OpenTx openTx = openTxes.remove(nextKey);
openTx.tx.close();
}
}
@ -309,7 +315,7 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
// OK. Move on
}
}
open.trace.release(this);
open.dispose(this);
}
closed.complete(null);
plugin.listeners.invoke().disconnected(this);
@ -840,7 +846,7 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
protected ReplyCloseTrace handleCloseTrace(RequestCloseTrace req) {
OpenTrace open = requireOpenTrace(req.getOid());
openTraces.removeById(open.doId);
open.trace.release(this);
open.dispose(this);
return ReplyCloseTrace.getDefaultInstance();
}
@ -968,13 +974,27 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
Msg.error(this, "Back-end debugger aborted a transaction!");
tx.tx.abortOnClose();
}
tx.tx.close();
OpenTrace open = requireOpenTrace(tx.txId.doId);
if (!tx.undoable) {
open.trace.clearUndo();
/**
* The listener is invoked via runLater, so we must do the same here, so that events are
* processed in the order emitted.
*/
Swing.runLater(() -> open.txListener.markNotUndoable());
}
tx.tx.close();
final boolean restoreEvents;
synchronized (openTxes) {
restoreEvents = openTxes.keySet()
.stream()
.noneMatch(id -> id.doId.domObjId == req.getOid().getId());
}
if (restoreEvents) {
open.trace.setEventsEnabled(true);
}
// TODO: Check for other transactions on the same trace?
open.trace.setEventsEnabled(true);
return ReplyEndTx.getDefaultInstance();
}
@ -1278,7 +1298,7 @@ public class TraceRmiHandler extends AbstractTraceRmiConnection {
@Override
public void forceCloseTrace(Trace trace) {
OpenTrace open = openTraces.removeByTrace(trace);
open.trace.release(this);
open.dispose(this);
}
@Override