From feaf8e2d49bc3df41dfbc92b89364b6ddfbe9844 Mon Sep 17 00:00:00 2001
From: ghidra1
Date: Thu, 18 Apr 2024 11:58:33 -0400
Subject: [PATCH 1/2] GP-4531 Corrected Ghidra Server deadlock
---
.../java/db/buffers/RemoteBufferFileImpl.java | 86 ++++++++++---------
.../server/remote/RepositoryHandleImpl.java | 60 ++++---------
2 files changed, 60 insertions(+), 86 deletions(-)
diff --git a/Ghidra/Features/GhidraServer/src/main/java/db/buffers/RemoteBufferFileImpl.java b/Ghidra/Features/GhidraServer/src/main/java/db/buffers/RemoteBufferFileImpl.java
index 1f07ec84c4..1f15f7d840 100644
--- a/Ghidra/Features/GhidraServer/src/main/java/db/buffers/RemoteBufferFileImpl.java
+++ b/Ghidra/Features/GhidraServer/src/main/java/db/buffers/RemoteBufferFileImpl.java
@@ -36,18 +36,20 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
implements RemoteBufferFileHandle, Unreferenced {
// Tracks open handles by user repository connection: maps repository handle instance to list of open file handles
- private static HashMap> instanceOwnerMap =
+ private static final HashMap> instanceOwnerMap =
new HashMap<>();
// Tracks open handles by path: maps "repo-name:" to list of open buffer file handles
- private static HashMap> instancePathMap = new HashMap<>();
+ private static final HashMap> instancePathMap =
+ new HashMap<>();
protected final RepositoryHandleImpl owner;
protected final String associatedFilePath;
- private LocalBufferFile bufferFile;
+ private final String clientHost;
+ private final LocalBufferFile bufferFile;
+
private boolean disposed = false;
- private String clientHost;
/**
* Construct a remote wrapper for a buffer file.
@@ -68,7 +70,6 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
}
this.clientHost = RepositoryManager.getRMIClient();
addInstance(this);
-//System.out.println("Constructed remote buffer file (" + instanceID + "): " + bufferFile);
}
private static String getFilePathKey(RemoteBufferFileImpl rbf) {
@@ -95,7 +96,6 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
instancePathMap.put(filePathKey, list);
}
list.add(rbf);
- rbf.owner.fireOpenFileCountChanged();
}
private static synchronized void removeOwnerInstance(RemoteBufferFileImpl rbf) {
@@ -104,7 +104,6 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
if (list.isEmpty()) {
instanceOwnerMap.remove(rbf.owner);
}
- rbf.owner.fireOpenFileCountChanged();
}
}
@@ -118,6 +117,29 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
}
}
+ /**
+ * Dispose and unexport all RemoteBufferFileImpl instances associated with the
+ * specified owner.
+ * @param owner
+ * @return true if one or more buffer files were disposed.
+ */
+ public static synchronized boolean dispose(Object owner) {
+ boolean found = false;
+ List list = instanceOwnerMap.remove(owner);
+ if (list != null) {
+ for (RemoteBufferFileImpl rbf : list) {
+ found = true;
+ rbf.dispose();
+ }
+ }
+ if (found) {
+ // If files were found, may need to repeat since pre-save
+ // files may have been constructed during dispose
+ dispose(owner);
+ }
+ return found;
+ }
+
/**
* Get the number of open RemoteBufferFileHandle's associated with the
* specified owner repository handle.
@@ -172,46 +194,26 @@ public class RemoteBufferFileImpl extends UnicastRemoteObject
dispose();
}
- /**
- * Dispose and unexport all RemoteBufferFileImpl instances associated with the
- * specified owner.
- * @param owner
- * @return true if one or more buffer files were disposed.
- */
- public static synchronized boolean dispose(Object owner) {
- boolean found = false;
- List list = instanceOwnerMap.remove(owner);
- if (list != null) {
- for (RemoteBufferFileImpl rbf : list) {
- found = true;
- rbf.dispose();
- }
- }
- if (found) {
- // If files were found, may need to repeat since pre-save
- // files may have been constructed during dispose
- dispose(owner);
- }
- return found;
- }
-
/**
* Dispose associated buffer file and unexport this instance.
*/
@Override
- public synchronized void dispose() {
- // must handle concurrent invocations
- if (!disposed) {
- try {
- unexportObject(this, true);
+ public void dispose() {
+
+ removeOwnerInstance(this);
+ removePathInstance(this);
+
+ synchronized (this) {
+ if (!disposed) {
+ try {
+ unexportObject(this, true);
+ }
+ catch (NoSuchObjectException e) {
+ // ignore
+ }
+ bufferFile.dispose();
+ disposed = true;
}
- catch (NoSuchObjectException e) {
- // ignore
- }
- removeOwnerInstance(this);
- removePathInstance(this);
- bufferFile.dispose();
- disposed = true;
}
}
diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RepositoryHandleImpl.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RepositoryHandleImpl.java
index 559d2491b3..0bbbae1f1a 100644
--- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RepositoryHandleImpl.java
+++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RepositoryHandleImpl.java
@@ -39,8 +39,8 @@ import ghidra.util.exception.FileInUseException;
* RepositoryHandleImpl provides a Repository handle to a
* remote user.
*/
-public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteRepositoryHandle,
- Unreferenced {
+public class RepositoryHandleImpl extends UnicastRemoteObject
+ implements RemoteRepositoryHandle, Unreferenced {
// private final RepositoryChangeEvent NULL_EVENT = new RepositoryChangeEvent(
// RepositoryChangeEvent.REP_NULL_EVENT, null, null, null, null);
@@ -191,8 +191,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
}
RepositoryChangeEvent openFileCountEvent =
- new RepositoryChangeEvent(RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT, null, null,
- null, Integer.toString(RemoteBufferFileImpl.getOpenFileCount(this)));
+ new RepositoryChangeEvent(RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT, null, null, null,
+ Integer.toString(RemoteBufferFileImpl.getOpenFileCount(this)));
synchronized (eventQueue) {
if (clientActive) {
@@ -213,31 +213,6 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
dispose();
}
- public void fireOpenFileCountChanged() {
-// if (!isValid) {
-// return;
-// }
-//
-// RepositoryChangeEvent event =
-// new RepositoryChangeEvent(RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT, null, null,
-// null, Integer.toString(RemoteBufferFileImpl.getOpenFileCount(this)));
-// synchronized (eventQueue) {
-//
-// // Remove existing queued event
-// Iterator iterator = eventQueue.iterator();
-// while (iterator.hasNext()) {
-// RepositoryChangeEvent queuedEvent = iterator.next();
-// if (queuedEvent.type == RepositoryChangeEvent.REP_OPEN_HANDLE_COUNT) {
-// iterator.remove();
-// break;
-// }
-// }
-//
-// eventQueue.add(event);
-// eventQueue.notifyAll();
-// }
- }
-
@Override
public RepositoryChangeEvent[] getEvents() throws IOException {
synchronized (eventQueue) {
@@ -414,16 +389,15 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
if (folder == null) {
throw new IOException("Failed to create repository Folder " + parentPath);
}
- LocalManagedBufferFile bf =
- folder.createDatabase(itemName, fileID, bufferSize, contentType, currentUser,
- projectPath);
+ LocalManagedBufferFile bf = folder.createDatabase(itemName, fileID, bufferSize,
+ contentType, currentUser, projectPath);
return new RemoteManagedBufferFileImpl(bf, this, getPathname(parentPath, itemName));
}
}
@Override
- public RemoteManagedBufferFileImpl openDatabase(String parentPath, String itemName,
- int version, int minChangeDataVer) throws IOException {
+ public RemoteManagedBufferFileImpl openDatabase(String parentPath, String itemName, int version,
+ int minChangeDataVer) throws IOException {
synchronized (syncObject) {
validate();
RepositoryFile rf = getFile(parentPath, itemName);
@@ -481,9 +455,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
validate();
repository.validateWritePrivilege(currentUser);
checkFolderInUse(oldParentPath, oldFolderName);
- RepositoryFolder folder =
- repository.getFolder(currentUser, oldParentPath + FileSystem.SEPARATOR +
- oldFolderName, false);
+ RepositoryFolder folder = repository.getFolder(currentUser,
+ oldParentPath + FileSystem.SEPARATOR + oldFolderName, false);
RepositoryFolder newParent = repository.getFolder(currentUser, newParentPath, true);
if (folder != null) {
folder.moveTo(newParent, newFolderName, currentUser);
@@ -511,9 +484,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
}
private void checkFileInUse(String parentPath, String itemName) throws FileInUseException {
- String[] openFileUsers =
- RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
- getPathname(parentPath, itemName));
+ String[] openFileUsers = RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
+ getPathname(parentPath, itemName));
if (openFileUsers != null) {
StringBuffer buf = new StringBuffer("");
for (String user : openFileUsers) {
@@ -553,9 +525,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
if (rf.hasCheckouts()) {
return true;
}
- String[] openFileUsers =
- RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
- getPathname(folder.getPathname(), rf.getName()));
+ String[] openFileUsers = RemoteBufferFileImpl.getOpenFileUsers(repository.getName(),
+ getPathname(folder.getPathname(), rf.getName()));
if (openFileUsers != null) {
return true;
}
@@ -622,7 +593,8 @@ public class RepositoryHandleImpl extends UnicastRemoteObject implements RemoteR
}
@Override
- public ItemCheckoutStatus[] getCheckouts(String parentPath, String itemName) throws IOException {
+ public ItemCheckoutStatus[] getCheckouts(String parentPath, String itemName)
+ throws IOException {
synchronized (syncObject) {
validate();
RepositoryFile rf = getFile(parentPath, itemName);
From 43d0034f3c7bb71ad55f05200cdfe9b7d15815f7 Mon Sep 17 00:00:00 2001
From: ghidra1
Date: Thu, 18 Apr 2024 13:02:54 -0400
Subject: [PATCH 2/2] GP-4523 Updated Help for Disassociate Action
---
.../data_type_manager_archives.html | 26 ++++++++++++++-----
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_archives.html b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_archives.html
index 3f14ebe017..4a95227fde 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_archives.html
+++ b/Ghidra/Features/Base/src/main/help/help/topics/DataTypeManagerPlugin/data_type_manager_archives.html
@@ -259,25 +259,37 @@
Disassociating Data Types
- You can arrive at the Disassociate Data Types
- dialog from the Disassociate Datatypes From
- action on an archive. The following dialog illustrates disassociating datatypes in a
- program named WinHelloCPP.exe that originated
- from a source archive named MyArchive.
+ You can disassociate the source archive relationship for datatypes within a
+ specific archive/program by selecting the Disassociate Datatypes From
+
<Source Archive Name>
+ popup action on the corresponding tree node within the
+ Data Type Manager.
+ If associated datatypes are found they will be listed in the Disassociate Data Types
+ dialog shown below. The sample case illustrates disassociating datatypes in a
+ program named WinHelloCPP.exe that originated from a source archive named
+ MyArchive.

The Disassociate DataTypes dialog
displays a table that lists all the data types that are associated with a pariticular
- source archive. The table consists of the following columns:
+ source archive. After selecting the datatypes to be disassociated from the source
+ archive, as reflected by the Apply column, the Disassociate button
+ may be clicked to complete the operation.
+
+
All datatypes may be selected for disassociation
+ by right-clicking on the table and choosing the Select All popup action.
+
+ The table consists of the following columns:
Apply
The apply checkbox. Selecting the checkbox will mark the data type to be
- disassociated from the source archive.
+ disassociated from the source archive.
+
Status