GP-7051 - Fixed deadlock seen when saving a program

This commit is contained in:
dragonmacher
2026-07-09 12:33:20 -04:00
parent 1c8b7a1411
commit 1f1a5dc33c
@@ -26,7 +26,6 @@ import ghidra.program.model.util.VoidPropertyMap;
*/ */
public class PersistentOpenCloseManager implements OpenCloseManager { public class PersistentOpenCloseManager implements OpenCloseManager {
private boolean openByDefault = true; private boolean openByDefault = true;
private VoidPropertyMap booleanProperty;
private ProgramUserData programUserData; private ProgramUserData programUserData;
// Often, isOpen will be called on the same function address many times in a row so cache // Often, isOpen will be called on the same function address many times in a row so cache
@@ -35,32 +34,53 @@ public class PersistentOpenCloseManager implements OpenCloseManager {
private boolean cachedResult; private boolean cachedResult;
private String defaultOpenClosePropertyname; private String defaultOpenClosePropertyname;
private String owner;
private String propertyName;
private VoidPropertyMap cachedPropertyMap;
public PersistentOpenCloseManager(ProgramUserData data, String owner, String propertyName) { public PersistentOpenCloseManager(ProgramUserData data, String owner, String propertyName) {
this.owner = owner;
this.propertyName = propertyName;
this.defaultOpenClosePropertyname = propertyName + "Default"; this.defaultOpenClosePropertyname = propertyName + "Default";
programUserData = data; programUserData = data;
int tx = programUserData.startTransaction();
try {
booleanProperty =
programUserData.getBooleanProperty(owner, propertyName, true);
}
finally {
programUserData.endTransaction(tx);
}
// Get the default open state. Only addresses different from default have properties stored. // Get the default open state. Only addresses different from default have properties stored.
String functionState = String functionState =
programUserData.getStringProperty(defaultOpenClosePropertyname, "Open"); programUserData.getStringProperty(defaultOpenClosePropertyname, "Open");
openByDefault = functionState.equals("Open"); openByDefault = functionState.equals("Open");
} }
private VoidPropertyMap getExistingProperty() {
if (cachedPropertyMap != null) {
return cachedPropertyMap;
}
cachedPropertyMap = programUserData.getBooleanProperty(owner, propertyName, false);
return cachedPropertyMap;
}
private VoidPropertyMap getOrCreatePropertyMap() {
if (cachedPropertyMap != null) {
return cachedPropertyMap;
}
cachedPropertyMap = programUserData.getBooleanProperty(owner, propertyName, true);
return cachedPropertyMap;
}
@Override @Override
public boolean isOpen(Address address) { public boolean isOpen(Address address) {
VoidPropertyMap propertyMap = getExistingProperty();
if (propertyMap == null) {
return openByDefault;
}
if (address.equals(cachedAddress)) { if (address.equals(cachedAddress)) {
return cachedResult; return cachedResult;
} }
cachedAddress = address; cachedAddress = address;
boolean contains = booleanProperty.hasProperty(address); boolean contains = propertyMap.hasProperty(address);
cachedResult = openByDefault ? !contains : contains; cachedResult = openByDefault ? !contains : contains;
return cachedResult; return cachedResult;
} }
@@ -111,7 +131,8 @@ public class PersistentOpenCloseManager implements OpenCloseManager {
private void addAddressProperty(Address address) { private void addAddressProperty(Address address) {
int tx = programUserData.startTransaction(); int tx = programUserData.startTransaction();
try { try {
booleanProperty.add(address); VoidPropertyMap propertyMap = getOrCreatePropertyMap();
propertyMap.add(address);
} }
finally { finally {
programUserData.endTransaction(tx); programUserData.endTransaction(tx);
@@ -121,7 +142,8 @@ public class PersistentOpenCloseManager implements OpenCloseManager {
private void removeAddressProperty(Address address) { private void removeAddressProperty(Address address) {
int tx = programUserData.startTransaction(); int tx = programUserData.startTransaction();
try { try {
booleanProperty.remove(address); VoidPropertyMap propertyMap = getOrCreatePropertyMap();
propertyMap.remove(address);
} }
finally { finally {
programUserData.endTransaction(tx); programUserData.endTransaction(tx);
@@ -131,7 +153,8 @@ public class PersistentOpenCloseManager implements OpenCloseManager {
private void clearProperties() { private void clearProperties() {
int tx = programUserData.startTransaction(); int tx = programUserData.startTransaction();
try { try {
booleanProperty.clear(); VoidPropertyMap propertyMap = getOrCreatePropertyMap();
propertyMap.clear();
} }
finally { finally {
programUserData.endTransaction(tx); programUserData.endTransaction(tx);